美文网首页iOS大咖
isa 和 superclass

isa 和 superclass

作者: Miss_QL | 来源:发表于2019-01-31 11:53 被阅读2次

    OC对象的分类
    OC中的对象,简单来说可以分为三大类:instance 对象(实例对象)、class 对象(类对象)、meta-class 对象(元类对象)。

    isa
    三种对象在内存中分别存储着不同的内容,具体如下图所示:

    2DC901DD-819F-4F96-896B-EBC33EF41DD3.png

    Teacher 对象的 isa 指向 class 对象。当调用对象方法时,通过实例对象的 isa 找到类对象,最后找到类对象中存储的对象方法进行调用。
    class 对象的 isa 指向 meta-class 对象。当调用类方法时,通过类对象的 isa 找到元类对象,最后找到元类对象中存储的类方法进行调用。

    superclass
    假若当前存在 Person 类和 Teacher 类,其中 Person 类继承自 NSObject 类,Teacher 类继承自 Person 类,则各个 class 对象的 superclass 指针指向如下图所示:

    D97DA286-4AC1-4EA3-9B40-6286FAC94840.png
    当 Teacher 的 instance 对象要调用 Person 的对象方法时,会先通过 isa 找到 Teacher 的 class,然后通过 superclass 找到 Person 的 class,最后找到对象方法的实现进行调用。 同理,各个 meta-class 对象的 superclass 指针指向如下图所示: image.png

    当 Teacher 的 class 对象要调用 Person 的类方法时,会先通过 isa 找到 Teacher 的 meta-class,然后通过 superclass 找到 Person 的 meta-class,最后找到类方法的实现进行调用。

    isa、superclass总结
    借用一下网上很火的总结图(个人觉得很到位~)

    1915113-192158848b1ebe7d.png
    instance 的 isa 指向 class。
    class 的 isa 指向 meta-class。
    meta-class 的 isa 指向基类的 meta-class。

    class 的 superclass 指向父类的 class。如果没有父类,superclass 指向为 nil。
    meta-class 的 superclass 指向父类的 meta-class。基类的 meta-class 的 superclass 指向基类的 class。

    instance 调用对象方法的轨迹:isa 找到 class,方法不存在,就通过 superclass 找父类。
    class 调用类方法的轨迹:isa 找到 meta-class,方法不存在,就通过 superclass 找父类。

    相关问题
    为了考验大家对 isa 和 superclass 的理解程度,接下来我们探索个有趣的问题:
    首先创建一个 NSObject 的分类 NSObject (Utils) ,在其.m文件中实现对象方法 -classMethodTest
    再创建一个 QLPerson 类,在.h文件中声明类方法+ (void)classMethodTest,但.m文件中并无该方法实现。
    问:调用[QLPerson classMethodTest]; 方法会发生什么现象?

    //  NSObject+Utils.h
    #import <Foundation/Foundation.h>
    NS_ASSUME_NONNULL_BEGIN
    @interface NSObject (Utils)
    @end
    NS_ASSUME_NONNULL_END
    
    //  NSObject+Utils.m
    #import "NSObject+Utils.h"
    @implementation NSObject (Utils)
    - (void)classMethodTest {
        NSLog(@"%s", __func__);
    }
    @end
    
    //  main.m
    #import <Foundation/Foundation.h>
    #import "NSObject+Utils.h"
    
    @interface QLPerson : NSObject
    + (void)classMethodTest;
    @end
    @implementation QLPerson
    @end
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            [QLPerson classMethodTest];
        }
        return 0;
    }
    

    分析:
    根据前面所总结的,我们知道在调用[QLPerson classMethodTest];时,实际上是QLPerson 的 isa 先找到 QLPerson 的 meta-class,在 QLPerson 的 meta-class 中并没有找到+ classMethodTest方法的实现,接下来会通过 QLPerson 中 meta-class 的 superclass 指针去找父类 NSObject 的 meta-class,在 NSObject 的 meta-class 中也没有找到+ classMethodTest方法的实现,便会继续通过 NSObject 中 meta-class 的 superclass 指针去找其父类,因为 NSObject 是基类,故其元类的父类指向其类本身,即 NSObject 的 class。又因 NSObject 的 class 中存储的对象方法中包含了 -classMethodTest,所以方法找到了,调用即可。
    结果:
    最终的结果是会调用分类 NSObject (Utils) 的 -classMethodTest方法,打印结果如下:

    image.png

    好啦,先到此为止,后续若有新发现,会继续更新。 欢迎大家指正与分享~

    相关文章

      网友评论

        本文标题:isa 和 superclass

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