加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 金华站长网 (https://www.0579zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 业界 > 正文

Swift 5.0的Runtime机制浅析

发布时间:2019-07-18 18:38:39 所属栏目:业界 来源:欧阳大哥2013
导读:副标题#e# 导读:你想知道Swift内部对象是如何创建的吗?方法以及函数调用又是如何实现的吗?成员变量的访问以及对象内存布局又是怎样的吗?这些问题都会在这篇文章中得到解答。为了更好的让大家理解这些内部实现,我会将源代码翻译为用C语言表示的伪代码来实

如果是在Swift类的extension中定义的方法(重写OC基类的方法除外)。那么针对这个方法的调用总是会在编译时就决定,也就是说在调用这类对象方法时,方法调用指令中的函数地址将会以硬编码的形式存在。在extension中定义的方法无法在运行时做任何的替换和改变!而且方法函数的符号信息都不会保存到类的描述信息中去。这也就解释了在Swift中派生类无法重写一个基类中extension定义的方法的原因了。因为extension中的方法调用是硬编码完成,无法支持多态!下面的Swift源代码以及C伪代码实现说明了这个情况:

  1. ////////Swift源代码 
  2.  
  3. //类定义 
  4. class CA { 
  5.     open func foo(){} 
  6.  
  7. //类的extension定义 
  8. extension CA { 
  9.    open func extfoo(){} 
  10.  
  11. func main() { 
  12.   let obj = CA() 
  13.   obj.foo() 
  14.   obj.extfoo() 
  15.  
  16. ////////C伪代码 
  17.  
  18. //...........................................运行时定义部分 
  19.  
  20.  
  21. //Swift类描述。 
  22. struct  swift_class { 
  23.     ...   //其他的属性,因为这里不关心就不列出了。 
  24.    //虚函数表刚好在结构体的第0x50的偏移位置。 
  25.     IMP vtable[1]; 
  26. }; 
  27.  
  28.  
  29. //...........................................源代码中类的定义和方法的定义和实现部分 
  30.  
  31.  
  32. //类定义 
  33. struct CA { 
  34.       struct  swift_class *isa; 
  35.  
  36. //类的方法函数的实现定义 
  37. void foo(){} 
  38. //类的extension的方法函数实现定义 
  39. void extfoo(){} 
  40.  
  41. //类的描述信息构建,这些都是在编译代码时就明确了并且保存在数据段中。 
  42. //extension中定义的函数不会保存到虚函数表中。 
  43. struct swift_class classCA; 
  44. classCA.vtable[0] = {&foo}; 
  45.  
  46.  
  47. //...........................................源代码中程序运行的部分 
  48.  
  49. void main(){ 
  50.   CA *obj =  CA.__allocating_init(classCA) 
  51.   obj->isa = &classCA; 
  52.   asm("mov x20, obj"); 
  53.   //Swift中常规方法foo调用采用间接调用实现 
  54.   obj->isa->vtable[0](); 
  55.   //Swift中extension方法extfoo调用直接硬编码调用,而不是间接调用实现 
  56.   extfoo(); 

需要注意的是extension中是可以重写OC基类的方法,但是不能重写Swift类中的定义的方法。具体原因根据上面的解释就非常清楚了。

类中定义的常规方法

(编辑:PHP编程网 - 金华站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!