1. 类的普通方法调度

写一个结构体和一个类,对比看看方法调用的方式:

// 结构体
struct PersonStruct {
func changClassName() {}
} let s = PersonStruct()
s.changClassName() // 类
class PersonClass {
func changClassName() {}
} let c = PersonClass()
c.changClassName()

生成 SIL 代码:

【1】结构体及类的 SIL 代码:

与结构体不同的是:为PersonClass类自动生成了一个反初始化方法。

【2】执行方法的 SIL 代码:

在调用的方式中,可以看到类的方法,不是由function_ref 修饰而是class_method修饰。

【3】还有一个不同点是,SIL 中为 PersonClass 自动生成了sil_vtable

由上面 SIL 代码,我们可以看出,SIL 为类的方法创建了 sil_vtable,并在调用时,用class_method来修饰。这样的类的方法调度,是Swift 中动态派发的一种方式,叫做函数派发。

这里sil_vtable 关键字声明的就是函数表。 函数表初始化的源码如下:

从源码中看,函数表中的数据结构是一个数组,源码是以遍历的的方式去获取函数表内的函数的,所以函数表是按顺序存放类中可能是函数派发去执行的函数,但是不一定函数表内的函数都会被以函数派发的方式去调度。

2. OC 继承链中的方法列表存储结构

我们知道 OC 中的方法是消息派发的方式。 每个对象中都有一个 isa 指针,指向自己的类。类中存放着该类实现的方法列表。本类方法列表中存放着本类实现的方法及父类方法列表的指针。在消息派发时,会先查找本来的方法列表,如果没找到,再去查找父类的方法列表,以此类推,来寻找方法的实现。

假设A类继承B类,B类继承C类,如下图所示:

3. Swift 继承连中的函数表存储结构

Swift 类中数派发消息派发类似, 所有类也会维护一个自己的函数表, 不同的是所有未被复写的父类所实现的函数地址都会拷贝在这个表中, 而不是由一个指向父类方法表的指针替代, 被重写的函数,在函数表中会指定为子类中的函数。由于少了一步指针寻址步骤, 在派发效率上要比基于消息的派发高效

假设A类继承B类,B类继承C类,如下图所示:

代码验证一下:

Swift

 
 
class PersonClass: NSObject {
override init() {
super.init()
@objc func changClassName7() {}
dynamic func changClassName8() {}
}
} class PersonClassSub: PersonClass {
func runSub() {}
// 重写的函数,在函数表中会指定为子类中的函数
override func changClassName7() {}
} class PersonClassSubSub: PersonClassSub {
func runSubSub() {}
}

到这里,证实2件事情:

  • Swift的函数表是按顺序存放的
  • 在类的继承关系中,函数表中存放所有的方法,由上到下,依次排列,先是父类的方法,再是子类的方法。

以上为这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家支持。

青山不改,绿水长流,后会有期,感谢每一位佳人的支持!

 

Swift-方法调度-类的普通方法底层探究的更多相关文章

  1. C#中如果类的扩展方法和类本身的方法签名相同,那么会优先调用类本身的方法

    新建一个.NET Core项目,假如我们有如下代码: using System; namespace MethodOverload { static class DemoExtension { pub ...

  2. iOS Swift结构体与类的方法调度

    前言 hello,小伙伴们:在忙碌中闲暇之余给大家聊聊swift的知识点,今天给大家带来的是swift中结构体与类的方法调度详细区别,希望对你有所帮助,好了废话不用多说,接下来步入主题! 1.普通方法 ...

  3. Java Native Interfce三在JNI中使用Java类的普通方法与变量

    本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 前面我们学习了如何在JNI中通过参数来使用J ...

  4. Eclipse_常用技巧_01_自动添加类注释和方法注释

    一.步骤 路径A=windows-->preference-->Java-->Code Style-->Code Templates-->Comments 自动添加注释一 ...

  5. Math类的random()方法

    Math类的random()方法 Math类的random()方法可以生成大于等于0.0.小于1.0的double型随机数. Math.random()方法语句基础上处理可获得多种类型.或任意范围的随 ...

  6. Swift进阶之内存模型和方法调度

    前言 Apple今年推出了Swift3.0,较2.3来说,3.0是一次重大的升级.关于这次更新,在这里都可以找到,最主要的还是提高了Swift的性能,优化了Swift API的设计(命名)规范. 前段 ...

  7. swift 笔记 (十一) —— 方法(类,结构体,枚举)

    Methods (方法) 实例方法(Instance Methods) 我认为看到这里.我们唯能八一八的就是swift的自做主张的行为了,反正它就是会以各种方式帮助我们来完毕让代码看起来非常奇怪的事情 ...

  8. swift -- 类中的方法

    一. 引用类型  类 在类中定义方法 class Person { //属性 var name : String = "" //方法 //实例方法 : 在类里面创建一个方法 fun ...

  9. Java学习笔记之方法重载,动态方法调度和抽象类

    一.方法重载 如果子类中的方法与它的超类中的方法有相同的方法名,则称子类中的方法重载超类中的方法,特别是当超类和子类中的方法名和参数类型都相同时,在子类中调用该方法时,超类中的方法会被隐藏.考虑下面程 ...

随机推荐

  1. study day2

    study day2 windows 常用快捷键 CTRL C:复制 CTRL V:粘贴 CTRL A:全选 CTRL X:剪切 CTRL S:保存 CTRL Z:撤销 alt f4:关闭窗口 shi ...

  2. Windows Server 2022 OVF(SLIC 2.6)

    请访问原文链接:https://sysin.org/blog/windows-server-2022-ovf/,查看最新版.原创作品,转载请保留出处. 作者:gc(at)sysin.org,主页:ww ...

  3. 制作nginx+php的docker镜像方法

    制作nginx+php的docker镜像方法一.准备安装的工具工具:docker-17.06.0-ce.nginx-1.13.2.PHP-5.5.38 .supervisor配置思路:1.安装dock ...

  4. eclipse中的一些快捷键

    1.内容提示 Alt+/ 2.快速修复 ctrl+/ 3.导包 ctrl+shift+o 4.格式代码块 ctrl+shift+o 5.向前向后 Alt+方向键 6.添加注释 ctrl+shift+/ ...

  5. 手把手教你实现栈以及C#中Stack源码分析

    定义 栈又名堆栈,是一种操作受限的线性表,仅能在表尾进行插入和删除操作. 它的特点是先进后出,就好比我们往桶里面放盘子,放的时候都是从下往上一个一个放(入栈),取的时候只能从上往下一个一个取(出栈), ...

  6. PHP中的MySQLi扩展学习(四)mysqli的事务与预处理语句

    对于 MySQLi 来说,事务和预处理语句当然是它之所以能够淘汰 MySQL(原始) 扩展的资本.我们之前也已经学习过了 PDO 中关于事务和预处理语句相关的内容.所以在这里,我们就不再多讲理论方面的 ...

  7. Mysql Navicate 基础操作与SQL语句 版本5.7.29

    SQL数据的增删改查:此部分所有SQL语句在navicat中与mysql命令行执行效果一样,只是mysql服务端在命令行执行,而navicat只是在客户端的图形化打开操作. 一.进入数据库 .连接数据 ...

  8. django 安装redis及session使用redis存储

    环境:centos 7.4 第一:安装redis 下载redis并安装: wget http://download.redis.io/releases/redis-5.0.5.tar.gz yum - ...

  9. 牛客练习赛89E-牛牛小数点【数论】

    正题 题目链接:https://ac.nowcoder.com/acm/contest/11179/E 题目大意 定义\(f(x)\)表示\(\frac{1}{x}\)的混循环节长度(如果没有循环节就 ...

  10. WPF实现截图(仿微信截图)

    WPF开发者QQ群: 340500857  | 微信群 -> 进入公众号主页 加入组织 每日一笑 肚子疼,去厕所排便,结果什么都没拉出来.看着自己坐在马桶上痛苦又努力却一无所获的样子,仿佛看到了 ...