了解 Swift 如何在运行时确定方法执行,提升您对性能和代码效率的理解。了解 Swift 如何在运行时确定方法执行,提升您对性能和代码效率的理解。

Swift 方法调度的旅行者指南

2025/12/03 06:18
阅读时长 6 分钟
如需对本内容提供反馈或相关疑问,请通过邮箱 [email protected] 联系我们。

简介

方法调度是一种用于选择需要在调用时调用的适当方法的算法。方法调度的主要目标是向程序提供有关在内存中可以找到特定方法的可执行代码的信息。

方法调度的类型

编译语言有三种类型的方法调度:

  • 静态或直接调度
  • 表格或虚拟调度
  • 消息调度

静态调度

静态调度是Swift中最快的调度方法。由于没有可用的方法重写,因此方法只有一个实现,并且它位于内存中的单个位置。

\ 我们可以使用诸如staticfinalprivate等关键字来使用静态调度。

\ 静态调度是值类型的默认方法调度,因为值类型不能被重写。

\ 让我们看一些例子:

Final关键字

一旦我们向类添加final关键字,其方法就不支持重写,这时静态调度就会发挥作用。

// MARK: Final class final class ClassExample { // MARK: Static dispatch func method() { // implementation ... } }

协议扩展

一旦你使用扩展添加协议的默认实现,其调度方法就会切换到静态调度,而不是使用见证表。

// MARK: Prorocol Extension extension ProtocolExample { // MARK: Direct Dispatch func method() { // implementation ... } } class ClassExample2: ProtocolExample {} let classExample2 = ClassExample2() classExample2.method()

类扩展

当方法在扩展中实现时,这意味着它不能被子类重写。在这种情况下,有静态调度的空间。

// MARK: Example Class Extension class ClassExample3 {} extension ClassExample3 { // MARK: Direct Dispatch func method() { // implementation ... } } let classExample3 = ClassExample3() classExample3.method()

访问控制

我们不能在类体外访问私有方法。这意味着该方法不能被重写,并使用静态调度。

// MARK: Access Control class ClassExample4 { // MARK: Direct Dispatch private func method() { // implementation ... } }

表格调度

当我们必须处理继承时,会使用表格调度。这是Swift中使用的默认调度类型。

虚拟表

对于类或子类的每个实例,都会创建一个虚拟表,其中包含有关每个类已实现方法的信息,并存储对适当实现的引用。虚拟表调度的主要缺点是它的速度低于静态调度。

\ 让我们看一个例子:

// MARK: Virtual Table class ParentClass { func method1() {} func methdod2() {} } class ChildClass: ParentClass { override func method1() {} func method3() {} }

\ 对于每个实例,都会创建自己的虚拟表,如下所示:

\

见证表

见证表由协议使用,并为符合协议的每个类创建。CPU使用此表来确定应该在哪里查找适当的实现。符合协议的每种类型(值和引用)都有自己的协议见证表,其中包含指向协议所需的类型方法的指针。

\ 让我们看一个例子:

// MARK: Witness Table Dispatch protocol ProtocolExample { func method1() func method2() } class ClassExample1: ProtocolExample { func method1() {} func method2() {} } class ClassExample2: ProtocolExample { func method1() {} func method2() {} }

\ 在这种情况下,为每个类创建一个见证表:

\

消息调度

消息调度是最动态的方法调度风格。它在运行时寻找适当的实现。因为它在运行时操作,我们可以使用方法交换来更改方法实现。

\ 如果你想使用消息调度,你需要在方法实现前添加@objc dynamic

// MARK: Message Dispatch class ClassExample: NSObject { @objc dynamic func method() {} } class SubClassExample: ClassExample { @objc dynamic override func method() {} } let subclass = SubClassExample() subclass.method()

\ 在SubClassExample中搜索方法的实现。如果该类中没有此方法的实现,则搜索继续在父类中进行,依此类推,直到达到NSObject

\

让我们将所有类型合并到一个表格中:

\

结论

总之,Swift中的方法调度是代码执行的关键方面,影响性能和灵活性。通过选择正确的调度方法,开发人员可以优化他们的代码,确保适应性,并有效地利用Swift的动态特性。理解和掌握方法调度对于构建高效和适应性强的Swift应用程序至关重要。

免责声明: 本网站转载的文章均来源于公开平台,仅供参考。这些文章不代表 MEXC 的观点或意见。所有版权归原作者所有。如果您认为任何转载文章侵犯了第三方权利,请联系 [email protected] 以便将其删除。MEXC 不对转载文章的及时性、准确性或完整性作出任何陈述或保证,并且不对基于此类内容所采取的任何行动或决定承担责任。转载材料仅供参考,不构成任何商业、金融、法律和/或税务决策的建议、认可或依据。