NSObject没有父类,他是怎么来的呢(一)

来源:互联网 发布:淘宝美工临摹 编辑:程序博客网 时间:2024/04/28 10:04
在我们创建类的时候,都是继承与某一个类创建的,可是NSObject是没有父类,而NSObject是怎么来的呢?首先先让我们看看这个NSObject类中有哪些东西。很明显又一个Class结构体的指针 isa,Class是什么呢?我们点击进去看。他是一个objc_class的结构体的指针,可是objc_class中也是有一个Class的isa,结论,在objc的runtime中,类是用objc_class结构体表示的,对象是用objc_object结构体表示的每一个对象都有一个名为 isa 的指针(也就是指向这个对象在runtime中的结构体的内存地址),指向该对象的类。 对象的isa用来标示这个对象是哪个类的实例。那么元类的 isa 指针又指向哪里呢?苹果为了设计上的完整,isa 指针指向自己,这样就行成了一个闭环。即所有事物都是对象,都有 isa 指针。首先,这些源码是属于objc runtime的,庆幸的是objc runtime的源代码苹果已经开源了,点击打开链接。打开objc/Source/NSObject.mm这个文件,这就是NSObject的实现代码。大概浏览一遍,函数是不是有很多都非常熟悉呢?可以说这些函数接口我们每天都在用,这次终于该好好看看它们是怎么实现的了。 为了方便,我把其中一部分代码摘录出来 
  1. - (Class)class { 
  1.     return object_getClass(self); 
  1.  
  1. Class object_getClass(id obj) 
  1.     return _object_getClass(obj); 
  1.  
  1. static inline Class _object_getClass(id obj) 
  1.     if (obj) return obj->isa; 
  1.     else return Nil; 
代码非常直白,注意下最后这个函数:
  1. static inline Class _object_getClass(id obj) 
  1.     if (obj) return obj->isa; 
  1.     else return Nil; 
如果obj不空,返回的Class类型就是obj->isa,否则,返回的是Nil。这就从源码上证实了isa就是代表一个对象的类型。 通过上面的源码分析,我们搞明白了对于普通的对象实例,isa就是表明它所属的类型。通过调用 class等方法返回的其实就是这个isa变量。 下面我们再来分析一下类objc_class,为什么它也有一个isa变量呢?
  1. struct objc_class { 
  1.     Class isa; 
  1. }; 
在面向对象的设计中,万物皆对象,所以类(Class)也是一个对象,它也有一个isa,那么类的isa指向谁呢? 我们看这句代码[NSObject class],这里我们调用了+ (Class)class这个类方法,我们再开发中经常用到这个方法,它返回的是这个类所属的Class类型。这是不是就可以作为一个类也是一个对象的佐证呢? 我们继续看看objc runtime的源码,你可以在objc/Source/NSObject.mm这个文件中找到下面的代码:
  1. + (Class)class { 
  1.     return self; 
[NSObject class]这句代码返回的竟然是self,我们都知道对于一个类的实例来说,self总是指向其自身的,但是这里并没有实例啊,我们是直接调用了NSObject这个类的一个类方法+(Class)class啊。返回的是Class结构体,也就是self。 这个函数的返回值是一个类对象class object(也是结构体——objc_object),所以其本质上还是一个对象而已。既然是一个对象,它拥有一个self指针是不是就不奇怪了呢?现在我们就明白了,对于像NSObject这样的类来说,它其实代表的是一个类对象,本质上还是一个普通的实例对象,类对象的self指针应该指向的是这个类对象自身。明白了吧?但是关于self的详细介绍,很遗憾,需要到更低层,也就是 objc 语言层去寻找答案了。因为self是 objc 的保留关键字,所以,objc 需要为这个关键字提供语言层面上的支持,我们要找到答案,可以从self这条线索入手,看看 objc 到底是怎样实现的。
以上是我自己的研究,有什么问题请列举出来,大家共同学习。


1 0