medium - swift protocol and delegate example
No se admite el uso de algĂșn protocolo como tipo concreto conforme a otro protocolo (1)
La razón subyacente de la limitación es que Swift no tiene metatipos de primera clase. El ejemplo más simple es que esto no funciona:
func isEmpty(xs: Array) -> Bool {
return xs.count == 0
}
En teoría, este código podría funcionar, y si lo hiciera, habría muchos otros tipos que podría hacer (como Functor y Monad, que realmente no se pueden expresar en Swift hoy). Pero no puedes. Debes ayudar a Swift a clavar esto en un tipo concreto. A menudo hacemos eso con genéricos:
func isEmpty<T>(xs: [T]) -> Bool {
return xs.count == 0
}
Tenga en cuenta que
T
es totalmente redundante aquí.
No hay razón para que deba expresarlo;
nunca se usa
Pero Swift lo requiere para que pueda convertir la
Array
abstracta en el concreto
[T]
.
Lo mismo es cierto en su caso.
Este es un tipo concreto (bueno, es un tipo abstracto que se convertirá en un tipo concreto cada vez que se instancia y se completa
P
):
class ImplementProtocolA<P : ProtocolA>
Este es un tipo completamente abstracto que Swift no tiene ninguna regla para convertir en un tipo concreto:
class ImplementProtocolB : ImplementProtocolA<ProtocolB>
Necesitas hacerlo concreto. Esto compilará:
class ImplementProtocolB<T: ProtocolB> : ImplementProtocolA<T> {}
Y también:
class UserDemoPresenter<T: GetUserView> : Presenter {
typealias V = T
}
Solo porque es probable que te encuentres con el problema más tarde: tu vida será mucho más fácil si haces estas estructuras o clases
final
.
La mezcla de protocolos, genéricos y polimorfismo de clase está llena de bordes muy afilados.
A veces tienes suerte y simplemente no se compilará.
A veces llamará cosas que no esperas.
Quizás le interese Un poco de respeto por AnySequence que detalla algunos problemas relacionados.
private var presenter : UserDemoPresenter<GetUserView>
Este sigue siendo un tipo abstracto. Te refieres:
final class Something<T: GetUserView> {
private var presenter: UserDemoPresenter<T>
}
Si eso crea un problema, deberá crear un cuadro. Ver Protocolo no se ajusta a sí mismo? para una discusión sobre cómo se borra el texto para poder mantener los tipos abstractos. Pero necesitas trabajar en tipos concretos. En última instancia, no puede especializarse en un protocolo. Eventualmente debes especializarte en algo concreto en la mayoría de los casos.
Estoy tratando de mezclar genéricos con protocolos y me está costando mucho xD
Tengo cierta arquitectura implementada en un proyecto de Android / Java, y estoy tratando de reescribirla para que encaje en un proyecto rápido / iOS. Pero he encontrado esta limitación.
Protocolo A
protocol ProtocolA {
}
Protocolo B
protocol ProtocolB : ProtocolA {
}
ImplementProtocolA
class ImplementProtocolA <P : ProtocolA> {
let currentProtocol : P
init(currentProtocol : P) {
self.currentProtocol = currentProtocol
}
}
ImplementProtocolB
class ImplementProtocolB : ImplementProtocolA<ProtocolB> {
}
Entonces, cuando trato de establecer el Protocolo B como el tipo concreto que implementa el Protocolo A , obtengo este error:
No se admite el uso de ''Protocolo B'' como tipo concreto conforme al protocolo ''Protocolo A''
1 ¿Hay alguna razón para esta "limitación"?
2 ¿Hay alguna solución para implementar esto?
3 ¿Será compatible en algún momento?
--ACTUALIZADO--
Otra variante del mismo problema, creo:
Ver protocolos
protocol View {
}
protocol GetUserView : View {
func showProgress()
func hideProgress()
func showError(message:String)
func showUser(userDemo:UserDemo)
}
Protocolos de presentador
protocol Presenter {
typealias V : View
}
class UserDemoPresenter : Presenter {
typealias V = GetUserView
}
Error:
UserDemoPresenter.swift La coincidencia posiblemente prevista ''V'' (también conocida como ''GetUserView'') no se ajusta a ''Ver''
¿¿Que es eso?? Se ajusta!
Incluso si uso View en lugar de GetUserView, no se compila.
class UserDemoPresenter : Presenter {
typealias V = View
}
UserDemoPresenter.swift La coincidencia posiblemente prevista ''V'' (también conocida como ''Ver'') no se ajusta a ''Ver''
xxDD No lo entiendo, de verdad.
--ACTUALIZADO--
Con la solución propuesta por Rob Napier, el problema no se soluciona, sino que se retrasa.
Cuando intento definir una referencia a UserDemoPresenter, necesito especificar el tipo genérico, por lo que obtengo el mismo error:
private var presenter : UserDemoPresenter<GetUserView>
No se admite el uso de ''GetUserView'' como tipo concreto conforme al protocolo ''GetUserView''