ios – Swift – 如何在一个具体的子类中覆盖一个扩展方法

前端之家收集整理的这篇文章主要介绍了ios – Swift – 如何在一个具体的子类中覆盖一个扩展方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个扩展UIView实现一个协议
  1. protocol SomeProtocol {
  2. var property : Int
  3. }
  4. extension UIView : SomeProtocol {
  5. var property : Int {
  6. get {
  7. return 0
  8. }
  9. set {
  10. // do nothing
  11. }
  12. }
  13. }

在一个具体的子类中,我想覆盖这个扩展方法

  1. class Subclass : UIView,SomeProtocol {
  2. var _property : Int = 1
  3. var property : Int {
  4. get { return _property}
  5. set(val) {_property = val}
  6. }
  7. }

我设置断点,看到扩展方法调用,而不是具体的子类方法

  1. var subclassObject = Subclass()
  2.  
  3. someObject.doSomethingWithConcreteSubclassObject(subclassObject)
  4.  
  5. // other code;
  6.  
  7. fun doSomethingWithConcreteSuclassObject(object : UIView) {
  8. var value = object.property // always goes to extension class get/set
  9. }

解决方法

作为 others have noted,Swift不允许您覆盖在类扩展中声明的方法.然而,我不知道你是否会得到你想要的行为,即使/当Swift有一天允许你覆盖这些方法.

考虑Swift如何处理协议和协议扩展.给出一个打印一些Metasyntactic变量名称的协议:

  1. protocol Metasyntactic {
  2. func foo() -> String
  3. func bar() -> String
  4. }

提供默认实现的扩展:

  1. extension Metasyntactic {
  2. func foo() -> String {
  3. return "foo"
  4. }
  5.  
  6. func bar() -> String {
  7. return "bar"
  8. }
  9. }

还有一个符合协议的类:

  1. class FooBar : Metasyntactic {
  2. func foo() -> String {
  3. return "FOO"
  4. }
  5.  
  6. func bar() -> String {
  7. return "BAR"
  8. }
  9. }

Swift将根据每个变量的运行时类型而不是由编译器推断的类型,使用动态调度来调用foo()和bar()的相应实现:

  1. let a = FooBar()
  2. a.foo() // Prints "FOO"
  3. a.bar() // Prints "BAR"
  4.  
  5. let b: Metasyntactic = FooBar()
  6. b.foo() // Prints "FOO"
  7. b.bar() // Prints "BAR"

但是,如果我们进一步扩展协议以添加新的方法

  1. extension Metasyntactic {
  2. func baz() -> String {
  3. return "baz"
  4. }
  5. }

如果我们在符合协议的类中覆盖我们的新方法

  1. class FooBarBaz : Metasyntactic {
  2. func foo() -> String {
  3. return "FOO"
  4. }
  5.  
  6. func bar() -> String {
  7. return "BAR"
  8. }
  9.  
  10. func baz() -> String {
  11. return "BAZ"
  12. }
  13. }

Swift现在将根据编译器推断的类型使用静态调度来调用适当的baz()实现:

  1. let a = FooBarBaz()
  2. a.baz() // Prints "BAZ"
  3.  
  4. let b: Metasyntactic = FooBarBaz()
  5. b.baz() // Prints "baz"

Alexandros Salazar有a fantastic blog post explaining this behavior in depth,但足以说Swift只对原始协议中声明的方法使用动态调度,而不是在协议扩展中声明的方法.我想象同样的扩展类也是如此.

猜你在找的iOS相关文章