Me pregunto si es posible lograr tal cosa.
Tengo un patio de juegos como este:
protocol Foo {
func testPrint()
}
extension Foo {
func testPrint() {
print("Protocol extension call")
}
}
struct Bar: Foo {
func testPrint() {
// Calling self or super go call default implementation
self.testPrint()
print("Call from struct")
}
}
let sth = Bar()
sth.testPrint()
Puedo proporcionar una implementación predeterminada en, extension
pero ¿qué Bar
pasa si necesita todo lo que está en la implementación predeterminada más cosas adicionales?
De alguna manera es similar a llamar a super.
métodos en class
es para cumplir con el requisito de implementar todas las propiedades, etc. pero no veo posibilidad de lograr lo mismo con structs
.
Foo.testPrint(self)()
- el problema es que falla debido a una falla de segmentación (probado tanto en 7.0 GM como en 7.1 beta)Respuestas:
No sé si todavía está buscando una respuesta a esto, pero la forma de hacerlo es eliminar la función de la definición del protocolo, convertir su objeto
Foo
y luego llamar al método en él:protocol Foo { // func testPrint() <- comment this out or remove it } extension Foo { func testPrint() { print("Protocol extension call") } } struct Bar: Foo { func testPrint() { print("Call from struct") (self as Foo).testPrint() // <- cast to Foo and you'll get the default // function defined in the extension } } Bar().testPrint() // Output: "Call from struct" // "Protocol extension call"
Por alguna razón, solo funciona si la función no se declara como parte del protocolo, sino que se define en una extensión del protocolo. Imagínate. Pero funciona.
fuente
Foo
protocolo no hereda de ningún otro protocolo.Bueno, puede crear un tipo anidado que se ajuste al protocolo, instanciarlo y llamar al método en ese (no importa que no pueda acceder a los datos de su tipo, ya que la implementación dentro de la extensión del protocolo no puede hacer referencia a él de todos modos). Pero no es una solución que yo llamaría elegante.
struct Bar: Foo { func testPrint() { // Calling default implementation struct Dummy : Foo {} let dummy = Dummy() dummy.testPrint() print("Call from struct") } }
fuente
¡Gracias por la publicacion! Si coloca la definición de la función en el protocolo, cuando el objeto se convierte en el protocolo, solo ve la versión del objeto de la función y, dado que lo está llamando dentro de sí mismo, obtiene la nueva dirección de Apple ...
Probé una versión como esta:
import UIKit protocol MyProc { } protocol MyFuncProc { func myFunc() } extension MyProc { func myFunc() { print("Extension Version") } } struct MyStruct: MyProc, MyFuncProc { func myFunc() { print("Structure Version") (self as MyProc).myFunc() } } (MyStruct() as MyFuncProc).myFunc()
Esto da una salida de:
Structure Version Extension Version
fuente
En caso de que su protocolo tiene
associatedType
oSelf
requisitos, entonces el molde no funcionará. Para solucionar este problema, cree una implementación predeterminada "sombra" a la que puedan llamar tanto la implementación predeterminada regular como la del tipo conforme.protocol Foo { associatedType Bar } extension Foo { func testPrint() { defaultTestPrint() } } fileprivate extension Foo { // keep this as private as possible func defaultTestPrint() { // default implementation } } struct Bar: Foo { func testPrint() { // specialized implementation defaultTestPrint() } }
fuente
defaultXX()
es mucho más expresivo y legible que otras respuestas.¿Qué opinas de esa forma de solucionar esto?
protocol Foo { func testPrint() } extension Foo { func testPrint() { defaultTestPrint() } func defaultTestPrint() { print("Protocol extension call") } } struct Bar: Foo { func testPrint() { // Calling self or super go call default implementation defaultTestPrint() print("Call from struct") } } let sth = Bar() sth.testPrint()
fuente