OC中类和对象的本质

1.OC的对象

OC的对象其实是一个指向objc_object结构体的指针,结构体中只有一个isa指针,这个指针指向对象所属的类。

struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};

2.OC的类

类(Class)是一个指向objc_class结构体的指针,objc_class结构体包含isa指针、父类指针、方法列表、方法缓存、协议列表等。

其isa指针指向元类,super_class指针指向其父类,方法列表中存放的是实例方法。

当一个实例对象调用方法时,对象先根据其isa指针找到对应的类,然后在类的方法缓存中查找该方法的实现,如果查找到了就调用并终止查找;如果在方法缓存中没有查找到就在类的方法列表中查找,如果在方法列表中找到了就调用并将该方法添加到方法缓存中并终止查找;如果在当前类的方法列表中也没有查找到,就顺着super_class指针继续遍历父类的方法列表,如果找到了就调用并将该方法添加到当前类的方法缓存中并终止查找,一次递归直至找到方法实现,如果一直到父类为nil为止都没有找到方法实现就会进行消息转发,如果消息转发后依然没有被指向就会出现crash。这种将对象方法保存在类中的做法,使得通过同一个类实例化的对象共享了同一份实例方法的实现,对象本身只需要保存自己的独立的数据就好了,既节约了存储空间又极大提升了运行的速度。

// Class是一个指向objc_class结构体的指针
typedef struct objc_class *Class;

struct objc_class {
    Class isa;                                // 实现方法调用的关键
    
    #if !__OBJC2__
    Class super_class;                        // 父类
    const char * name;                        // 类名
    long version;                             // 类的版本信息,默认为0
    long info;                                // 类信息,供运行期使用的一些位标识
    long instance_size;                       // 该类的实例变量大小
    struct objc_ivar_list * ivars;            // 该类的成员变量链表
    struct objc_method_list ** methodLists;   // 方法定义的链表
    struct objc_cache * cache;                // 方法缓存
    struct objc_protocol_list * protocols;    // 协议链表
    #endif
};

注意:如果只是声明了方法但没有实现方法,这个方法是不会出现在方法列表中的。只要有方法的实现,即使没有方法声明,这个方法也在方法列表中。

3.OC的元类

上面objc_class结构体中也有个isa指针,所以OC中类其实也是一个对象,叫类对象,类对象的isa指向的类就是元类(metaClass)。元类的方法列表中存的是类方法。

当调用类方法时,首先根据类的isa指针找到元类,然后在元类的方法缓存中查找方法实现,如果没有找到就去元类的方法列表中查找,还是没有找到就去元类的父类的方法列表查找,直到找到方法实现或者父类为nil时为止。

4.对象、类、元类的关系

对象、类、元类的关系如下图所示。

  • 实例对象的isa指针指向该对象的类,该对象的实例方法保存在这个类的继承链中;
  • 类对象的isa指针指向该类的元类,类方法保存在元类的继承链中;
  • 元类和普通类一样也有父类,也具备自己的继承关系链;
  • 所有元类的isa指针都是指向元类的根类(包括元类的根类的isa指针也是指向它自己);
  • 注意元类的根类的super_class指针指向类的根类。
对象、类、元类

你可能感兴趣的:(OC中类和对象的本质)