我有一个协议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
但预计 - 吧
我如何从我的test()
调用实例方法tester
这完全取决于两件事:
例如:
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"
。
如果在协议中声明函数,则使用见证表动态调度它,即如果从派生实现调用它,则将获得被覆盖的版本。如果在扩展中声明函数(并且未在协议中声明),则会静态调度该函数,并根据您调用它的类型(即没有多态性)获取版本。这样做的原因是编译器必须在编译时知道协议函数和变量声明以生成见证表,并且在编译时它无法知道所有可能的扩展。