Swift: ¿Cómo puedo anular un método de extensión en una subclass concreta?

Tengo una extensión en UIView implementando un protocolo

protocol SomeProtocol { var property : Int } extension UIView : SomeProtocol { var property : Int { get { return 0 } set { // do nothing } } } 

En una subclass concreta, deseo anular este método de extensión:

 class Subclass : UIView, SomeProtocol { var _property : Int = 1 var property : Int { get { return _property} set(val) {_property = val} } } 

Pongo puntos de interrupción y veo que se llame al método de extensión y no al método de subclass concreto:

 var subclassObject = Subclass() someObject.doSomethingWithConcreteSubclassObject(subclassObject) // other code; fun doSomethingWithConcreteSuclassObject(object : UIView) { var value = object.property // always goes to extension class get/set } 

Como otros han observado , Swift no (todavía) le permite anular un método declarado en una extensión de class. Sin embargo, no estoy seguro de si alguna vez obtendrá el comportamiento que desea incluso si / cuando Swift algún día le permite anular estos methods.

Considere cómo Swift trata con los protocolos y las extensiones de protocolo. Dado un protocolo para imprimir algunos nombres de variables metasintácticas:

 protocol Metasyntactic { func foo() -> String func bar() -> String } 

Una extensión para proporcionar implementaciones pnetworkingeterminadas:

 extension Metasyntactic { func foo() -> String { return "foo" } func bar() -> String { return "bar" } } 

Y una class que se ajusta al protocolo:

 class FooBar : Metasyntactic { func foo() -> String { return "FOO" } func bar() -> String { return "BAR" } } 

Swift usará el despacho dynamic para llamar a las implementaciones apropiadas de foo() y bar() function del tipo de time de ejecución de cada variable en lugar del tipo inferido por el comstackdor:

 let a = FooBar() a.foo() // Prints "FOO" a.bar() // Prints "BAR" let b: Metasyntactic = FooBar() b.foo() // Prints "FOO" b.bar() // Prints "BAR" 

Sin embargo, si extendemos el protocolo para agregar un nuevo método:

 extension Metasyntactic { func baz() -> String { return "baz" } } 

Y si anulamos nuestro nuevo método en una class que se ajusta al protocolo:

 class FooBarBaz : Metasyntactic { func foo() -> String { return "FOO" } func bar() -> String { return "BAR" } func baz() -> String { return "BAZ" } } 

Swift ahora utilizará el envío estático para llamar a la implementación apropiada de baz() function del tipo inferido por el comstackdor:

 let a = FooBarBaz() a.baz() // Prints "BAZ" let b: Metasyntactic = FooBarBaz() b.baz() // Prints "baz" 

Alexandros Salazar tiene una fantástica publicación de blog que explica este comportamiento en profundidad , pero basta con decir que Swift solo usa el envío dynamic para los methods declarados en el protocolo original, no para los methods declarados en las extensiones de protocolo. Me imagino que lo mismo sería cierto para las extensiones de class, también.

Parece que puedes anular la propiedad de la propiedad de la segunda superclass. Por ejemplo, puede acceder a la propiedad UIView haciendo una extensión a la UILabel desee anular la propiedad de frame de UIView . Esta muestra me funciona en Xcode 6.3.2

 extension UILabel { override public var frame: CGRect { didSet { println("\(frame)") } } } 

Creo que olvidó anular la propiedad de la superclass en su subclass:

 class Subclass : UIView { var _property : Int = 1 override var property : Int { get { return _property} set(val) {_property = val} } } 
Intereting Posts