如果多个类都实现了 MyProtocol,在运行时,当通过协议类型调用方法时,系统怎么确认应该用哪个 Witness Table ?

在 Swift 中,如果多个类都实现了同一个协议,系统在运行时通过协议类型调用方法时,会使用与具体实例类型对应的 Witness Table 来确认应该调用哪一个实现。这是通过在实例对象中维护对其具体类型的元数据(metadata)的引用来实现的。

运行时如何选择合适的 Witness Table

1. 协议定义和类型实现

首先,让我们定义一个协议和多个实现该协议的类:

protocol MyProtocol {
    func doSomething()
}

class ClassA: MyProtocol {
    func doSomething() {
        print("ClassA implementation")
    }
}

class ClassB: MyProtocol {
    func doSomething() {
        print("ClassB implementation")
    }
}
2. 实例化和协议类型引用

接下来,我们创建 ClassAClassB 的实例,并通过 MyProtocol 类型引用这些实例:

let instanceA: MyProtocol = ClassA()
let instanceB: MyProtocol = ClassB()
3. 调用协议方法

当通过 MyProtocol 类型调用方法时,Swift 使用以下机制来确定具体的实现:

instanceA.doSomething()  // 输出 "ClassA implementation"
instanceB.doSomething()  // 输出 "ClassB implementation"
4. 运行时类型检查和 Witness Table 查找

运行时类型信息
每个 Swift 对象实例都包含一个指向其类型元数据的指针。这个元数据包含该类型实现的所有协议的相关信息,包括协议的 Witness Table。

查找 Witness Table 的过程

  1. 获取实例的类型元数据:当调用 doSomething 方法时,Swift 首先通过实例的元数据指针获取其类型元数据。
  2. 查找协议的 Witness Table:类型元数据中包含该类型实现的所有协议的 Witness Table 的指针。Swift 通过协议的标识符在元数据中找到对应的 Witness Table。
  3. 调用具体实现:通过找到的 Witness Table,Swift 调用具体的 doSomething 方法实现。

示例详细解析

protocol MyProtocol {
    func doSomething()
}

class ClassA: MyProtocol {
    func doSomething() {
        print("ClassA implementation")
    }
}

class ClassB: MyProtocol {
    func doSomething() {
        print("ClassB implementation")
    }
}

let instanceA: MyProtocol = ClassA()
let instanceB: MyProtocol = ClassB()

instanceA.doSomething()  // 输出 "ClassA implementation"
instanceB.doSomething()  // 输出 "ClassB implementation"
实现步骤
  1. 实例化对象

    • instanceAClassA 的实例,instanceBClassB 的实例。
  2. 协议类型引用

    • instanceAinstanceB 都被声明为 MyProtocol 类型,这意味着在调用协议方法时,需要动态确定具体实现。
  3. 运行时调用

    • 调用 instanceA.doSomething() 时,Swift 通过 instanceA 的元数据找到 ClassA 的 Witness Table,并调用 ClassAdoSomething 实现。
    • 调用 instanceB.doSomething() 时,Swift 通过 instanceB 的元数据找到 ClassB 的 Witness Table,并调用 ClassBdoSomething 实现。

元数据和 Witness Table 结构

元数据

  • 每个类型的元数据包含类型的基本信息、方法表、属性表以及实现的协议表。

Witness Table

  • 对于每个实现了某个协议的类型,编译器会生成一个对应的 Witness Table,包含该类型对协议中所有方法和属性的具体实现。

总结

在 Swift 中,当多个类实现了同一个协议时,系统在运行时通过实例对象的类型元数据和对应的 Witness Table 来确定具体调用哪个实现。每个实例对象包含一个指向其类型元数据的指针,通过这个指针,Swift 能够找到并使用正确的 Witness Table 来执行协议方法的具体实现。这种机制保证了协议调用的灵活性和高效性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

依旧风轻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值