六、类的本质和结构

1,365 阅读3分钟

本文由快学吧个人写作,以任何形式转载请表明原文出处。

一、资料准备

objc4-818.2 : github.com/LGCooci/KCO…

对应mac的版本是11.1。可根据自己的系统版本挑选可以进行调试的源码。

二、探索思路

1、创建一个对象,获取这个对象的类

2、利用clang,将源码编译。

3、查看编译后的类。

4、找到类的数据结构。

5、在源码内进行一层一层的剖析。

三、创建项目

创建一个自定义的类,继承于NSObject。在818.2的main.m中创建这个类的实例对象,然后用Class获取这个实例对象的类信息。用Class的原因是oc中所有的类都可以用Class来接收。所以具有普遍性。

图片.png

从terminal终端进入项目所在的文件夹,进入到main.m所在的文件夹下,然后用clang进行编译,clang命令 : clang -rewrite-objc main.m -o main.cpp

在生成的main.cpp文件中查找自定义的类,例如我自定义的JDPerson,会发现JDPerson是一个objc_object结构体。

图片.png

再看Class是什么结构。查找Class,硬找太困难,所以找规律,看JDPerson,发现一个类被编译后,可以发现它的本质的地方,都有一种格式 : "类 + ;"。

所以搜索Class;,一共49个,很好找,Class的本质也是结构体,是objc_class结构体,如下图 :

图片.png

所以普通的继承类的本质是objc_object,而Class编译后的本质是objc_class。这是在这里得到的一个信息。

四、源码探索类的本质

源码中查找objc_class :

图片.png

可以得到的信息是 :

  1. objc_class是一个继承于objc_object的结构体
  2. objc_class有四个成员,但是成员ISA被注释。

为什么ISA成员被注释?但是还要放在代码里面,其实是相当于占位,告诉看到这里的人,这里是应该有一个ISA的。既然子类没有,那么ISA就应该是继承于父类的,所以查找objc_object的源码,如下 :

图片.png

找到了ISA。从上述源码,可以得到的信息是,所谓的万物皆对象,就是万物皆objc_object。一切类的源头,就是objc_object。

而我们常说的万物皆NSObject,和这里是否有冲突?查看NSObject的定义,在源码中找到NSObject.h文件 :

图片.png

可以看到NSObject的定义和objc_object的结构是完全一样的,也就是说,NSObject是objc_object的一种仿写。objc_object是编译后的结构,NSObject是编译前的定义,所以万物皆NSObject也是没有问题的,并不冲突。

五、为什么isa是Class类型

  1. 万物皆对象,isa也是对象,也可以由Class接收。

  2. 从isa的来源来看,源码中搜索Class isa,找到isa的来源如下 :

图片.png

  1. 找getIsa() :

图片.png

  1. ISA()源码 :

图片.png

  1. getDecodedClass源码 :

图片.png

  1. getClass源码 :

图片.png

从6中的图可以看到,返回的类型,会被强转为Class。也可以说明为什么isa是Class类型的。

六、总结

  1. Class(类)的本质是objc_class
  2. objc_class是继承于objc_object的结构体
  3. 由上述两点可以得出,类的本质是objc_object。并且可以得出,万物皆对象。
  4. NSObject是OC仿写的objc_object,所以万物是NSObject与万物是objc_object是不冲突的。
  5. 类的结构体中有四个重要的成员,分别是isa(继承于objc_object),superclass(父类),cache(缓存),bits(数据)。