类在runtime中的描述如下:
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
} ;
当然,以上是简化过的,略去了不重要的内容。
再来看下Class的定义
typedef struct objc_class *Class;
合并一下,就能得到下面的等效表达
struct objc_class {
struct objc_class *isa;
};
那么对象呢?同样,来看描述
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
typedef struct objc_object *id;
Class的定义跟上面类的描述一致,所以也可以合并为
struct objc_object {
struct objc_class *isa;
};
我们这两个定义放在一起来看下:
struct objc_class {
struct objc_class *isa;
};
struct objc_object {
struct objc_class *isa;
};
typedef struct objc_class *Class; //类 (class object)
typedef struct objc_object *id; //对象 (instance of class)
通过上面的声明可以看出,Class是一个指向objc_class结构体的指针,而id是一个指向objc_object结构体的指针,其成员isa是一个指向objec_class结构体的指针。
凡是首地址是*isa的struct指针,都可以被认为是objc中的对象。运行时可以通过isa指针,查找到该对象是属于什么类,也就是当我们向某个对象发送某个消息时,运行时库会根据实例对象的isa指针找到这个实例对象所属的类。Runtime库会在类的方法列表及父类的方法列表中去寻找与消息对应的selector指向的方法。
所有的类自身也是一个对象,我们可以向这个对象发送消息(即调用类方法)。如:
NSString *string = [NSString string];
我们给NSString发送了一个string的消息,也就是可以把NSString也看成是一个对象,那么它就包含一个指向其所属类的指针了,这个指针是指向啥的呢?这就是接下来我们要说的meta-class了。它是一个类对象所属的类。当我们向一个对象发送消息时,runtime会在这个对象所属的这个类的方法列表中查找方法;而向一个类发送消息时,会在这个类的meta-class的方法列表中查找。
好了,又一个问题来了,meta-class也是一个类,也可以向它发送一个消息,那么它的isa又是指向什么呢?为了不让这种结构无限延伸下去,Objective-C的设计者让所有的meta-class的isa指向基类的meta-class,以此作为它们的所属类。即,任何NSObject继承体系下的meta-class都使用NSObject的meta-class作为自己的所属类,而基类的meta-class的isa指针是指向它自己,实在是机智。
根据上面我们讲的,就能得到下面这张经典的类与对象的关系图了,可以比对这张图再重读下上面说的,能理解得更透彻点。
1510064850760.jpg
网友评论