swift类方法为什么使用表派发?

直接上答案:因为表派发允许子类重写父类的方法,并在运行时根据对象的实际类型调用正确的方法实现。

什么是表派发?

首先我们先知道的是,swift当中函数的派发机制主要分为静态派发和动态派发。动态派发又分为表派发和消息派发。

静态派发(直接派发)

静态派发的速度非常快,因为编译器能在编译时定位指令所在的位置(编译时就会绑定方法)。因此函数被调用时候,编译器直接跳转到函数的内存地址来执行操作。所以就会非常快。使用静态派发的主要是所有的值类型,扩展的方法,以及用final,static的修饰的类和属性。(由于stuct和enum是值类型,且不支持继承,所以编译器把方法放在静态派发)

扩展的方法为什么也是静态派发?

这里我们首先要明白扩展的本质:扩展的用途是为现的类型添加新的功能,而不修改原有类型的定义。

·扩展的方法在编译期间就会被静态的绑定到类型本身

·扩展不能参与类型的继承链

·扩展没有动态和多态,不能覆盖原有类型或字类中的方法。

扩展(extension)不会额外增加运行时的存储空间,因为扩展的本质是在编译期对类型的功能进行静态增强,而不是动态地向类型添加新成员(存储属性会改变类型的内存布局,而扩展被设计为一种编译时功能增强机制。如果允许扩展添加存储属性,会导致类型的内存布局不确定,影响已有代码的兼容性)。扩展是对类型的附加行为,扩展方法不参与类的继承体系,因此不能支持动态派发(多态)。

表(table)派送

表派送只要是利用一个表,该表是一组函数指针,成为witness table(虚拟表),实际上就是swift的运行时表,用来查找特定方法的实现。

witness如何工作的呢?

·每个子类都有自己对于此表的拷贝

·对于此类重写的每个方法,此表都有不同的函数指针

·对于子类添加新方法时,这些方法指针将附加到数组的结尾。

·最后编译器在表中查看为方法调用的具体实现

由于编译器必须从表中读取方法实现的内存地址,然后跳转地址,由于要执行两条指令,所以他比静态派发要慢,但比Message要快。使用表派发的主要是类的实例方法和子类可重写的方法。

消息(Message)派发

消息派发是一种动态派发机制,通过运行时的消息传递来调用方法。他不是直接调用方法的内存地址,而是把消息发送给对象,由对象动态解析方法。在swift中,消息派发主要是支持OC的动态特性,例如方法替换等(Method Swizzing)和运行时(runtime)消息解析。主要用于@objc和dynamic的方法。

回到最开始的为什么要使用表派发?主要是因为支持class的继承和方法的重写(多态),因为这些需要根据对象的实际类型来调用方法。静态派发的话,对象的动态类型无法在编译期间确定。

相关推荐
报错小能手1 天前
ios开发方向——Swift语言学习 为啥要学Swift?
学习·ios·swift
旭久1 天前
react+echarts实现2d地图标记点与影响区域及可拖拽放大缩小等功能
react.js·echarts·swift
游戏开发爱好者81 天前
入门 iOS 开发 新手工具开发首个应用
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
2501_915106322 天前
不依赖 Mac 也能做 iOS 开发?跨设备开发流程
ide·vscode·macos·ios·个人开发·swift·敏捷流程
2501_915921433 天前
VSCode 写 Swift 运行到 iPhone?快蝎 IDE 开发实战体验
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
东坡肘子3 天前
我的 App 审核被卡了? -- 肘子的 Swift 周报 #128
人工智能·swiftui·swift
奶糖的次元空间5 天前
iOS 学习笔记 - SwiftUI 和 简单布局
ios·swift
2501_915918416 天前
有没有Xcode 替代方案?在快蝎 IDE 中完成 iOS 开发的过程
ide·vscode·ios·个人开发·xcode·swift·敏捷流程
songgeb7 天前
Compositional layout in iOS
ios·swift·设计
1024小神7 天前
记录xcode项目swiftui配置APP加载启动图
前端·ios·swiftui·swift