Swift - 三种函数派发

2022-01-03  本文已影响0人  yyggzc521

Swift 的函数派发可以分为 静态动态 两种机制,而动态派发又分为 函数表派发消息派发

Swift 函数的派发方式和 对象类型、函数声明位置 有关。

简单来说,静态派发在编译期能确定函数的内存地址,从而直接找到对应实现;
函数表派发通过读取函数表 vtable 找到对应的函数指针;
消息派发则为 objc_msgsend 方式;这三种派发方式可查看如下链接文章进行了解(网址:https://betterprogramming.pub/a-deep-dive-into-method-dispatches-in-swift-65a8e408a7d0?gi=cac13485c979 )。
由于在调用效率上,静态派发 > 函数表派发 > 消息派发,如果能减少不必要的动态派发,运行时函数调用速度得到显著提升。

动态派发的目的是支持函数多态,如果对于不需要重写的函数,可以用 final 修饰符修饰,编译器会将函数优化为静态派发。

使用 final, private 优化派发方式

如果对象只在声明的文件中可见,可以用 private 或 fileprivate 进行修饰。编译器会对private 或 fileprivate对象进行检查,确保没有其他继承关系的情形下,自动打上final标记,进而使得对象获得静态派发的特性。

需要注意的是,单独使用 @objc 修饰函数并不会使得函数派发变成消息派发,@objc 的作用仅是将 Swift 函数暴露给 Objective-C 调用,所以 @objc 可以和 final, private 关键词一起修饰函数定义。

调用结构体方法的本质

在 OC 中,调用一个方法的本质是消息传递,底层通过 objc_msgSend 函数去查找方法并调用。而 Swift 是一门静态语言,没有运行时的机制,那原生的 Swift 方法又是如何调用的呢?

在 Swift 中,调用一个结构体的方法是直接拿到函数的地址直接调用,包括初始化方法,没有 OC 那么复杂的流程。

需要注意的是,结构体的类方法调用也和实例方法的调用一样,都是直接拿函数的地址调用。在 Swift 中声明一个类方法需要在 func 前家加上 static 关键字。

Swift 是一门静态语言,许多东西在运行的时候就可以确定了,所以才可以直接拿到函数的地址进行调用,这个调用的形式也可以称作静态派发。

上一篇 下一篇

猜你喜欢

热点阅读