Runtime系列(类与元类)

作者: 01_Jack | 来源:发表于2015-07-29 22:35 被阅读4371次

    这篇文章继 Runtime系列(引文)之后,仍然是一篇引导文,主讲类与元类。如果你读过 Runtime系列(引文),可能会在其中发现一个词:类对象。那么什么是类对象

    先看一段代码

    NSArray *arr = [NSArray array];
    

    他是怎么运行的?

    上篇文章中提到,[receiver message]底层会调用id objc_msgSend(id self, SEL op, ...)。再来回顾一下id是什么

    struct objc_object {
        Class isa  OBJC_ISA_AVAILABILITY;
    };
    
    typedef struct objc_object *id;
    

    id指向一个对象,可以猜测[NSArray array]中的NSArray也是一个对象。可NSArray怎么会是对象?这就要引出本文的另一个主角元类了。

    元类

    其实NSArray和arr一样,也是对象,叫做类对象

    Class.png

    可以看到,Class中也有个isa指针,他的指向就是自身的元类。

    元类是类对象的类,类对象是元类的实例。
    

    基于这种设计模式,不难发现:

    1.我们以前调用 "+" 开头的类方法实际是在调用元类的对象方法
    2.由于每个类有且只有一个,所以每个类对象都是其对应元类的单例
    

    那么,元类是对象吗?
    答案是肯定的,元类是对象。
    如果元类也是对象,元类的类又是什么?

    元类的类

    再来看一张网上的示意图

    示意图.png
    • 图解
      我们接触到的大部分OC对象都继承自NSObject,这里直接以NSObject为例。
    1.每个实例对象的类都是类对象,每个类对象的类都是元类对象,每个元类对象的类都是根元类(root meta class的isa指向自身)
    2.类对象的父类最终继承自根类对象NSObject,NSObject的父类为nil
    3.元类对象(包括根元类)的父类最终继承自根类对象NSObject
    

    可见,类与元类是一个闭环。

    相关文章

      网友评论

      • 麟young:根元类的子类是元类,元类的对象是类,类的对象是对象。这样理解对吗?
        f48ab9e63152:是错的, 实例对象, 类对象, 元类对象 他们之间的关系就有所指向的指针,并不是父子类关系。每个实例对象的类都是类对象,每个类对象的类都是元类对象,每个元类对象的类都是根元类(root meta class的isa指向自身)
      • 我是C:请问,方便给个联系方式吗,有些问题不是很清楚 NSArray *arr = [NSArray array]; arr指向isa结构体, 结构体的里的 class isa 指向的是元类的结构体对象(NSArray)是这么理解吗
      • 星期五__:小白想问两个问题,看了作者写的,果然还是不懂啊,第一,那个一开始问题中NSSArray既然是个类对象,他的元类具体又叫什么呢。
        第二,那我在NSArray.h里面的+ (instancetype)array;方法明明有声明啊。。
        作者能不能屈尊来解答一下。。
        星期五__:@01_Jack 懂了,非常感谢,谢谢解答我的疑问
        01_Jack:@与狼同行 第二个问题没明白你想表达什么
        01_Jack:@与狼同行 你好,我所知道的方法中无法直接得到元类的类型,但是可以通过地址进行比较,如果有更好的方法希望告知 :smile:


        >>isa是受保护的,无法直接访问
        >>在类对象中调用`+ (Class)class`返回仍然是本身,底层调用`objc_getClass`,`objc_getMetaClass`同样返回类对象本身


        比较地址的代码可以这样写
        ```
        NSArray *arr = [NSArray array];
        Class cls = [arr class];
        int i = 0;

        while (1) {
        NSLog(@"%d---cls:%p---nsobject:%p", i, cls, objc_getMetaClass("NSObject"));

        i++;
        if (cls == objc_getMetaClass("NSObject")) break;

        cls = object_getClass(cls);
        }

        ```

      本文标题:Runtime系列(类与元类)

      本文链接:https://www.haomeiwen.com/subject/nrbmqttx.html