我有一个扩展UIView实现一个协议
protocol SomeProtocol { var property : Int } extension UIView : SomeProtocol { var property : Int { get { return 0 } set { // do nothing } } }
在一个具体的子类中,我想覆盖这个扩展方法:
class Subclass : UIView,SomeProtocol { var _property : Int = 1 var property : Int { get { return _property} set(val) {_property = val} } }
var subclassObject = Subclass() someObject.doSomethingWithConcreteSubclassObject(subclassObject) // other code; fun doSomethingWithConcreteSuclassObject(object : UIView) { var value = object.property // always goes to extension class get/set }
解决方法
作为
others have noted,Swift不允许您覆盖在类扩展中声明的方法.然而,我不知道你是否会得到你想要的行为,即使/当Swift有一天允许你覆盖这些方法.
考虑Swift如何处理协议和协议扩展.给出一个打印一些Metasyntactic变量名称的协议:
protocol Metasyntactic { func foo() -> String func bar() -> String }
提供默认实现的扩展:
extension Metasyntactic { func foo() -> String { return "foo" } func bar() -> String { return "bar" } }
还有一个符合协议的类:
class FooBar : Metasyntactic { func foo() -> String { return "FOO" } func bar() -> String { return "BAR" } }
Swift将根据每个变量的运行时类型而不是由编译器推断的类型,使用动态调度来调用foo()和bar()的相应实现:
let a = FooBar() a.foo() // Prints "FOO" a.bar() // Prints "BAR" let b: Metasyntactic = FooBar() b.foo() // Prints "FOO" b.bar() // Prints "BAR"
extension Metasyntactic { func baz() -> String { return "baz" } }
如果我们在符合协议的类中覆盖我们的新方法:
class FooBarBaz : Metasyntactic { func foo() -> String { return "FOO" } func bar() -> String { return "BAR" } func baz() -> String { return "BAZ" } }
Swift现在将根据编译器推断的类型使用静态调度来调用适当的baz()实现:
let a = FooBarBaz() a.baz() // Prints "BAZ" let b: Metasyntactic = FooBarBaz() b.baz() // Prints "baz"
Alexandros Salazar有a fantastic blog post explaining this behavior in depth,但足以说Swift只对原始协议中声明的方法使用动态调度,而不是在协议扩展中声明的方法.我想象同样的扩展类也是如此.