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

时间:2019-03-23 04:23:59

标签: swift swift-protocols

我有一个协议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

2 个答案:

答案 0 :(得分:1)

这完全取决于两件事:

  • 这是协议的要求还是仅仅是由扩展注入的?
  • 接收器是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"

答案 1 :(得分:0)

如果您在协议内部声明该函数,则会使用见证表动态分派该函数;即,如果您以衍生实现的形式调用该函数,则将获得重写的版本。如果您在扩展中声明该函数(并且未在协议中声明),则该函数将被静态分派,并且您将基于调用它的类型获得版本(即无多态性)。这样做的原因是,编译器必须在编译时知道协议函数和变量声明才能生成见证表,并且无法在编译时知道所有可能的扩展。