运行时,Swift 如何知道使用哪个实现?

10
protocol A {
    func f()
}

struct S1 : A {
    func f() {
        print("S1")
    }
}

struct S2 : A {
    func f() {
        print("S2")
    }
}

let array: [A] = [S1(), S2()]

for s: A in array {
    s.f()
}

// "S1\n" "S2\n"

如果这是一个继承层次结构,我会期望Swift使用虚函数表来查找正确的实现。然而,在array中的具体类型可能是任何实现A以及任意数量其他协议的类型,那么如果Swift也在使用虚函数表,Swift运行时如何知道对象的结构呢?


4
Swift使用“协议见证表”来实现这一点 - 这个WWDC演讲解释得非常好:https://developer.apple.com/videos/play/wwdc2016-416/?time=1474 - Hamish
太棒了,有趣的是,我今天已经计划好要观看那个视频了。 :) - Ian Warburton
本来要回复,但是没错,看那个讲座 :) - uraimo
1个回答

16

Swift运行时使用Protocol Witness Table来保存每种类型对协议方法的实现指针。

Mike Ash在他的文章《探索Swift内存布局,第二部分》中最好地解释了这一点:

偏移量为32的最后一个是底层类型与协议的"protocol witness table",其中包含类型对协议方法实现的指针。这是编译器能够在运行时调用协议类型的方法,例如p(),而不知道底层类型的方式。

我还建议看一下WWDC视频《了解Swift性能》,正如Hamish在评论中所建议的那样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接