You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 示例代码中的方法调用采用哪种方法派发机制?

Swift协议方法派发机制问题解析

你给出的示例中,aaaa.printSome()调用采用静态派发,不会经过协议witness table完成方法寻址,最终执行AAA类中的实现,输出结果为B。

核心逻辑说明:

  • 派发方式的判断核心首先看调用方的静态类型:示例中aaaa通过AAA()直接初始化,没有做协议类型的向上转型,编译阶段编译器就能100%确定该实例的静态类型为具体类AAA,因此会直接将方法调用静态绑定到AAA内部实现的printSome(),不需要运行时查表。
  • 你之前对静态派发的认知存在偏差:静态派发并非仅适用于方法只有单一实现的场景,只要编译阶段编译器能唯一确定调用目标的实现地址,就会采用静态派发,和方法存在多少个重写/默认实现没有直接关系。
  • witness table的触发有明确前提:只有当调用方的静态类型是协议类型(即把实例作为BBBB类型持有)时,对协议本身明确声明的方法的调用才会走witness table动态派发。举个对比例子:
    let b: BBBB = AAA()
    b.printSome() // 此时才会通过witness table查找实现,最终同样输出B
    
    如果printSome()没有写在BBBB的协议声明里,仅定义在协议扩展中,那么哪怕AAA实现了同名方法,以BBBB类型持有实例调用时,也会静态绑定到协议扩展的默认实现输出A,不会走witness table。
  • 你查到的“扩展中的方法采用静态派发”的结论是准确的:类扩展中新增的方法、协议扩展中提供的方法默认都是静态派发;只有协议本体声明的必需方法,在调用方为协议类型时,才会通过witness table完成动态派发。

原问题示例代码:

protocol BBBB {
    func printSome()
}

extension BBBB {
    func printSome() {
        print("A")
    }
}

class AAA { }

extension AAA: BBBB {
    func printSome() {
        print("B")
    }
}

let aaaa = AAA()
aaaa.printSome()

内容的提问来源于stack exchange,提问作者Pyrettt Pyrettt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 09:42:23