前言

  • 方法是 Swift 中的一个重要概念,方法允许你把需要复用的代码封装进方法中,这样当你调用方法时,实际上你的想法是执行方法中的那些代码,方法的出现极大的提高了方法的复用性。

  • Swift 工程的环境是非常复杂的,如何凭借方法的名字正确的找到方法中的代码实际上并不是听起来那样简单,在寻找代码的道路上又静态派发和动态派发两种不同的方式。

1、动态派发

  • OC 程序员应该不会对动态派发感到陌生,OC 中的方法都是动态派发的,也就是我们常说的消息转发。

  • 动态派发是指需要在运行时找到方法的具体实现。

    • Swift 中的动态派发和 OC 中的动态派发类似,在运行时程序会根据被调用的方法的名字去内存中的方法表中查表,找到方法的实现并执行。
    • 虽然动态派发的执行效率不如静态派发高,但是在很多情况下动态派发是合理的,比如异构数组中的方法调用使用的就是动态派发,这是因为静态派发的设计哲学与异构数组的设计初衷在本质上是互斥的。
  • 动态派发在编译时编译器不能知道某个方法的具体实现,这与方法调用时的上下文密切相关。

    • 比如当对象的上下文是一个协议时,运行时传入的必须是协议的遵守者,而不同遵守者中的同一个方法会有多个版本的实现,由于这种方法实现的不确定性,编译器无法完成静态派发,所以需要在运行时通过判断实例的真实身份,找到与之匹配的代码并执行。
    • 类似的还有父类与子类的情况。
  • 多态是编程语言中 “不确定性” 的典型代表,动态派发机制为多态提供了支撑,在 Swift 中继承和协议都具有多态的特性。

2、静态派发

  • 静态派发是指在运行时调用方法不需要查表,直接跳转到方法的代码中执行。

    • 很显然静态派发是一种更高效的方法,因为静态派发免去了查表操作。
    • 不过静态派发是有条件的,方法内部的代码必须对编译器透明,并且在运行时不能被更改,这样编译器才能帮助我们。
    • Swift 中的值类型不能被继承,也就是说值类型的方法实现不能被修改或者被复写,因此值类型的方法满足静态派发的要求。
  • 静态派发为 “内联” 或者其它优化提供了支持。

    • 支持 “内联” 的方法要求方法本身必须是静态派发的。
    • 不像 C 语言使用关键字 inline 注明内联,Swift 中值类型的方法是默认执行内联的。
    • 内联是指在编译期把每一处方法调用替换为直接执行方法内部的代码,可以帮助你避免运行时方法调用的时间开销。
05-11 20:02