2015-11-28 8 views
6

consideri il seguente:Swift estensione protocollo di esecuzione con un altro protocollo comune tipo associato

protocol Foo { 
    typealias A 
    func hello() -> A 
} 
protocol FooBar: Foo { 
    func hi() -> A 
} 
extension FooBar { 
    func hello() -> A { 
    return hi() 
    } 
} 

class FooBarClass: FooBar { 
    typealias A = String 
    func hi() -> String { 
    return "hello world" 
    } 
} 

Questo codice compila. Ma se commento la definizione esplicita del tipo associato typealias A = String, allora per qualche ragione, swiftc non riesce a dedurre il tipo.

che sto sentendo questo ha a che fare con due protocolli che condividono lo stesso tipo di associato ma senza un'affermazione diretta attraverso, ad esempio, il tipo di parametrizzazione (tipo forse associato non è potente/abbastanza maturo?), Che lo rende ambiguo per l'inferenza di tipo.

Non sono sicuro che si tratti di un bug/immaturità della lingua, o forse, mi mancano alcune sfumature nell'estensione del protocollo che giustamente portano a questo comportamento.

Qualcuno può far luce su questo?

+0

quando dici rapido non riesce a dedurre il tipo, qual è l'errore del compilatore e su quale linea? –

+0

@PatrickGoley Swift non riesce a vedere 'hello()' e 'hi()' 'restituisce il tipo 'A' per essere di tipo equivalente e, quindi, mi impone di implementare anche il metodo' hello() '. Dice 'FooBarClass' non riesce a conformarsi al protocollo' FooBar' –

+2

Penso che questo dovrebbe essere considerato come un bug. La soluzione che ho trovato sta dichiarando 'typealias' nel protocollo' FooBar'. cioè: 'protocollo FooBar: Foo {typealias A; func hi() -> A} ' – rintaro

risposta

0

Per la conformità a detto protocollo è necessario fornire valori espliciti per i tipi associati in un protocollo. Questo può essere realizzato con un duro codifica di un tipo, come hai fatto con typealias A = String, o utilizzando un tipo parametrico come lei ha ricordato, come di seguito:

class FooBarClass<T>: FooBar { 
    typealias A = T 
    ... 
} 

Swift non dedurre il tipo associato da un metodo implementato su il protocollo, in quanto potrebbero esserci ambiguità con più metodi con tipi di mismatching. Questo è il motivo per cui le tipealie devono essere risolte esplicitamente nella tua classe di implementazione.

+0

Potresti approfondire "come potrebbero esserci ambiguità con più metodi con tipi di mismatching"? –

1

un'occhiata a questo esempio

protocol Foo { 
    typealias A 
    func hello() -> A 
} 
protocol FooBar: Foo { 
    typealias B 
    func hi() -> B 
} 
extension FooBar { 
    func hello() -> B { 
     return hi() 
    } 
} 

class FooBarClass: FooBar { 
    //typealias A = String 
    func hi() -> String { 
     return "hello world" 
    } 
} 

con i generici

class FooBarClass<T>: FooBar { 
    var t: T? 
    func hi() -> T? { 
     return t 
    } 
} 

let fbc: FooBarClass<Int> = FooBarClass() 
fbc.t = 10 
fbc.hello() // 10 
fbc.hi() // 10 
+1

Vale la pena ricordare che si tratta di un bug nel compilatore Swift e che 'B' può essere denominato come' A'. –

Problemi correlati