isa 和 superclass

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

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

isa 和 superclass_第1张图片
2DC901DD-819F-4F96-896B-EBC33EF41DD3.png

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

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

isa 和 superclass_第2张图片
D97DA286-4AC1-4EA3-9B40-6286FAC94840.png

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

同理,各个 meta-class 对象的 superclass 指针指向如下图所示:
isa 和 superclass_第3张图片
image.png

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

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

isa 和 superclass_第4张图片
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 
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 
#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)