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

我有一个扩展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只对原始协议中声明的方法使用动态调度,而不是在协议扩展中声明的方法.我想象同样的扩展类也是如此.

相关文章

当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple...
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只...
一般在接外包的时候, 通常第三方需要安装你的app进行测...
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应...