Ho un protocollo my swift code base Ho protocollo con un tipo associato e due metodi. Entrambi i metodi definiscono diversi vincoli generici per il tipo associato del protocollo. E vorrei rendere la struttura conforme al protocollo due ma con due diversi tipi associati.implementare il protocollo con diverso tipo associato
protocol Convertable {
associatedtype TargetType
func convert() -> TargetType
}
func show<T : Convertable where T.TargetType == String>(toShow : T) {
print(toShow.convert())
}
func add<T : Convertable where T.TargetType == Int>(a : T, b : T) -> Int {
return a.convert() + b.convert()
}
struct MyData {
var data : Int
}
Come estensione faccio la struct conforme al protocollo in cui la TargetType
sarà String
per passare al metodo spettacolo:
extension MyData : Convertable {
func convert() -> String { return String(self.data) }
}
Finora tutto funziona come previsto. Ma ora mi piace anche che la struttura sia conforme al protocollo Convertable
quando TargetType
è associato a un Int. Quale sembra essere impossibile?
La prima cosa che ho provato è stato quello di aggiungere un secondo definizione del metodo convertito alla estensione:
extension MyData : Convertable {
func convert() -> String { return String(self.data) }
func convert() -> Int { return data }
}
Il compilatore ora lamenta che MyData
fa non è più conforme al protocollo. Il secondo era dividere questo in due estensioni e associare esplicitamente il TargetType.
extension MyData : Convertable {
typealias TargetType = Int
func convert() -> Int { return data }
}
extension MyData : Convertable {
typealias TargetType = String
func convert() -> String { return String(data) }
}
Questo ha l'effetto che il compilatore ora si lamenta il il TargetType
è stato ridefinito.
Il mio ultimo tentativo è stato quello di definire due protocolli che estendono il protocollo Convertable
e vincolare la TargetType
e quindi implementare entrambi tramite estensione:
protocol ConvertableString : Convertable {
associatedtype TargetType = String
}
protocol ConvertableInt : Convertable {
associatedtype TargetType = Int
}
extension MyData : ConvertableInt {
func convert() -> Int { return self.data }
}
extension MyData : ConvertableString {
func convert() -> String { return String(self.data) }
}
Il che rende ora il compilatore felice per le estensioni, ma non più per la chiamata a show
perché non sa che può chiamare la funzione con MyData
.
C'è qualcosa che ho supervisionato o non è attualmente possibile in swift?
Non è solo al momento non possibile, ma difficilmente sarà mai possibile, a mio parere. Hai dichiarato un protocollo con _one single_tipo associato. Come può essere impostato su due diversi tipi allo stesso tipo ?! – werediver
Beh, non è lo stesso protocollo, dal momento che il protocollo è generico su TargetType ci sono tante varianti del protocollo come per TargetType. L'intera idea di avere tipi associati ai protocolli è che è possibile differenziare il tipo associato. Se si guarda C#, è possibile implementare la stessa interfaccia con tipi diversi legati al parametro generico. – Kolja
Beh, non è C# e non dovresti pensarlo come sarebbe, perché semplicemente non funziona. – werediver