我有一个协议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
答案 0 :(得分:1)
这完全取决于两件事:
例如:
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"
。
答案 1 :(得分:0)
如果您在协议内部声明该函数,则会使用见证表动态分派该函数;即,如果您以衍生实现的形式调用该函数,则将获得重写的版本。如果您在扩展中声明该函数(并且未在协议中声明),则该函数将被静态分派,并且您将基于调用它的类型获得版本(即无多态性)。这样做的原因是,编译器必须在编译时知道协议函数和变量声明才能生成见证表,并且无法在编译时知道所有可能的扩展。