译文 - Swift中的方法派发

原文地址:https://zagahr.me/Method-dispatch-in-Swift/

在Swift中,每当程序调用一个方法时,方法派发机制(Method Dispatch)都会被触发,它的作用是告诉程序应该去哪里寻找要执行的方法。理解“方法派发机制”背后的概念,对于Swift编程尤为重要,因为一旦你不知道“方法派发机制”背后的玄机,这个机制可能会给你编写的程序带来性能问题。

方法派发分为两种:静态派发(Static Dispatch)和动态派发(Dynamic Dispatch)。

静态派发(Static Dispatch)

静态派发也被称为直接派发(Direct Dispatch),它是最快且最高效的一种方法派发类型。在编译阶段,编译器就已经知道了所有被静态派发的方法在内存中的地址,因而在运行阶段,这些方法可以被立即执行。
对于动态派发的方法,编译器不知道它的内存地址,读不到代码,因而也就无法对代码进行优化,结果就可能导致一些性能问题的出现。不过呢,动态派发可以为覆写父类中的方法提供支持,使得Swift也可以实现多态。

动态派发(Dynamic Dispatch)

动态派发包括两种不同的类型:表派发(Table Dispatch)和消息派发(Message Dispatch)。

表派发是编译型语言中实现动态派发最常用的方式。在编译阶段,编译器会为每一个类创建一个vtable,在这个表中存放的是一个包含若干函数指针的数组,这些指针指向这个类中相应函数的实现代码。在运行阶段调用实现代码时,表派发需要比静态派发多执行两个指令(读和跳转)。

消息派发是最动态但也是最慢的一种派发技术。在派发消息后,runtime需要爬遍该类的整个层级体系,才可以确定要执行哪个方法实现。不过呢,这也为在运行阶段改变程序的行为提供了可能,也使得Swizzling技术得以实现。Objective-C非常依赖消息派发,同时,它通过Objective-C runtime为Swift也提供了消息派发这一功能。

如何分辨派发类型?

要想确定一个方法会被静态派发还是动态派发,你需要先知道这个方法是定义在哪里的,是定义在本体中的?还是定义在扩展中的?

译文 - Swift中的方法派发_第1张图片
派发类型对照表

此外,Swift还提供了一些不同的修饰符,用于修改方法被派发时的行为:

  • dynamic 用这个修饰符声明的方法在Objective-C runtime中是可以访问的,在调用它的时候,将采用消息派发。
  • final 用这个修饰符声明的方法,在被调用时,将采用静态派发的方式。
  • final @objc 用这个修饰符声明的方法,在被调用时,将采用消息派发的方式。
  • @nonojc 用这个修饰符声明的方法,在被调用时,将不再采用消息派发的方式。

你可能感兴趣的:(译文 - Swift中的方法派发)