Swift 协议和扩展,如果存在我需要调用实例方法

Swift protocol and extension, I need to call instance method if it present

我有一个协议 Foo 及其扩展如下:

protocol Foo {
    func test()    
}

extension Foo {
    func test() {
        print("foo")
    }
}

我也有 类 来自这样的协议:

class Bar: Foo {
    func test() {
        print("bar")
    }
}

测试人员如下:

func tester<T: Foo>(_ obj: T) {
   obj.test()
}

let myBar = Bar()
tester(myBar)

在输出中我有:

foo

但符合预期 - bar

如何从我的 tester

中调用实例方法 test()

如果您在协议内声明该函数,那么它会使用见证动态调度 table 即,如果您从派生实现中调用它,您将获得覆盖版本。如果您 声明 扩展中的函数(并且它未在协议中声明),那么该函数将被静态分派,并且您会根据调用它的类型获得版本(即没有多态性)。这样做的原因是编译器必须在编译时知道协议函数和变量声明才能生成见证table,而它无法在编译时知道所有可能的扩展。

这完全取决于两件事:

  • 这是协议的要求还是仅由扩展注入?
  • 接收器类型是 Foo 还是 Bar?

例如:

protocol Foo {
    // func test() // note we've commented this out!
}
extension Foo {
    func test() {
        print("foo")
    }
}
class Bar: Foo {
    func test() {
        print("bar")
    }
}
let myBar = Bar()
myBar.test() // bar
let myFoo : Foo = Bar()
myFoo.test() // foo

但是如果你取消注释我注释掉的行,现在你总是得到"bar"打印。