【iOS】类、元类、父类的关系

前言

最近在学习OC的过程中被学长问到了有关isKindOfClass 和 isMemberOfClass的区别,在分清这二者的区别前,笔者觉得有必要先了解类、元类、父类的关系
同时在网上其实已经有了许多有关类、元类、父类的关系的资料,笔者在这里仅仅记录学习的过程。

导入

众所周知我们的isKindOfClass 和 isMemberOfClass既有实例方法,也有类方法,加起来总共四种方法

在这里首先我们要明白OC的底层80%是C语言,平常创建的对象(类也属于对象,类对象)都转换成了底层C语言里面的结构体

类与对象的源码

我们这里给出类与对象源码的定义:

我们的类的实质上是一个结构体指针:

typedef struct objc_class *Class;  
struct objc_class {
    
      
    Class isa;  
    Class super_class;  
    const char *name;  
    long version;  
    long info;  
    long instance_size;  
    struct objc_ivar_list *ivars;  
    struct objc_method_list **methodLists;  
    struct objc_cache *cache;  
    struct objc_protocol_list *protocols;  
}; 

我们再来看看我们对象的定义

在这里插入图片描述
我们在我们的类的定义的代码中已经用typedef命名了我们的Class,Class实质上就是一个结构体指针,我们的isa指针指向这个对象所指向的类

我们有关元类的使用应该会在后面学习iOS的消息发送机制时学到,这里到后面会补充。因笔者并未学习过这部分知识,所以这里直接引用学长的定义:

OC的类其实也是一个对象,一个对象就要有一个它属于的类,意味着类也要有一个isa指针,指向其所属的类。那么类的类是什么?就是我们所说的元类(MetaClass),所以,元类就是类的所属类。

相同的,我们的元类也是类,那么应该也有它的所属类,这里就引出一张广为人知的OC图:
在这里插入图片描述
这里有几个英文单词我们需要理解一下。
首先是Meta:它的意思就是当前类属于元类
其次是isa:我们在上面提到了,isa实际上是一个指向当前对象所属类的指针

这样我们便可以总结出我们类、元类、父类的基本关系:

isa指向

  1. 实例对象的所属类实际上就是其所属类,我们的实例对象就是图中的Instance of Subclass。
    接下来我们的isa指向了我们的类,那么继续研究我们类的所属类。
  2. 从图中可以看出,我们类的所属类实际上就指向了我们的元类。
  3. 接下来我们再看我们的元类,我们所有元类的所属类实际上都是根元类,在笔者参考的资料中是这样理解的,因为我们OC中几乎所有的类都是NSObject的子类,所以我们的根元类也可以认为是我们的NSObject的元类。
  4. 接着我们再看图中根元类的虚线,根元类所属的类指向了它本身。

superClass指向

我们这里的superClass指向就是我们类的父类,到了这里其实就比较好理解了,元类与我们的类一样,其父类都是一层层往上的,而不像元类所属的类一样,全部指向我们的根元类

在这里唯一需要注意的是我们的根元类的父类是我们的根类,也可以理解为NSObject类。而NSObject类的父类就是nil了。

我们以我们的代码来查看我们所说结论的正确性:

/// 实例化
    NSObject *obj = [[NSObject alloc]init];
    Person *person = [[Person alloc]init];
    Student *student = [[Student alloc]init];
    /// 获取实例对象的isa。即类
    Class Object = object_getClass(obj);
    Class Person = object_getClass(person);
    Class Student = object_getClass(student);
    /// 通过名字获取类
    Class Object1 = objc_getClass("NSObject");
    Class Person1 = objc_getClass("Person");
    Class Student1 = objc_getClass("Student");
    /// 获取类的父类
    Class ObjectSup = class_getSuperclass(Object1);
    Class PersonSup = class_getSuperclass(Person1);
    Class StudentSup = class_getSuperclass(Student1);
    /// 获取类的元类
    Class ObjectMeta = objc_getMetaClass("NSObject");
    Class PersonMeta = objc_getMetaClass("Person");
    Class StudentMeta = objc_getMetaClass("Student");
    /// 获取元类的父类
    Class ObjectMetaSup = class_getSuperclass(ObjectMeta);
    Class PersonMetaSup = class_getSuperclass(PersonMeta);
    Class StudentMetaSup = class_getSuperclass(StudentMeta);
    /// 通过类的isa获取Class ,实际就是元类,所以PersonMeta1的地址和PersonMeta是一样的,StudentMeta1的地址和StudentMeta是一样的。
    Class ObjectMeta1 = object_getClass(Object1);
    Class PersonMeta1 = object_getClass(Person1);
    Class StudentMeta1 = object_getClass(Student1);
    /// 通过元类的isa获取Class, 实际都是根元类,所以PersonMetaIsa和StudentMetaIsa,ObjectMetaIsa的地址是一样的
    Class ObjectMetaIsa = object_getClass(ObjectMeta);
    Class PersonMetaIsa = object_getClass(PersonMeta);
    Class StudentMetaIsa = object_getClass(StudentMeta);

加上断点后编译结果:
在这里插入图片描述

本篇文章参考的资料:
iOS 通俗的理解类,父类,元类的关系
[iOS开发]类,父类,元类的关系总结

猜你喜欢

转载自blog.csdn.net/weixin_72437555/article/details/130691020