先从一段代码说起:
@interface Person : NSObject
@end
@implementation Person
@end
@interface Son : Person
@end
@implementation Son
- (instancetype)init
{
self = [super init];
if (self) {
NSLog(@"%@", [self class]);
NSLog(@"%@", [super class]);
}
return self;
}
@end
/// 打印结果:
Son
Son
都是Son
使用 clang -rewrite-objc 这个命令后,得到的中间代码有如下关键部分:
(void *)objc_msgSend)((id)self, sel_registerName("class")
(void *)objc_msgSendSuper)((__rw_objc_super){ (id)self, (id)class_getSuperclass(objc_getClass("Son")) }, sel_registerName("class")
从上述C++源码可以看出,[self class]和[super class]的区别只是:
objc_msgSend(id, SEL) 和 objc_msgSendSuper(__rw_objc_super *superclass, SEL) 的区别, 只是查找方法的起点不一样,前者是当前类Son,后者是父类Person。
objc_msgSendSuper最终也会转为objc_msgSend( (id)self, sel_registerName("class"))。
那不就是普通的消息发送的流程么,前者从Son开始找class方法,后者从父类Person开始找,由于两者都没有class方法,两者都来到基类NSObject,都调用基类的class方法。
查看runtime源码:
// NSObject.mm
-(Class)class {
return object_getClass(self);
}
// objc-class.mm
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
所以,其实两者都是去找self的isa指针指向的类对象,也就是Son。
super只是一个编译指令,其实消息接收者还是self, 也就是当前类的实例对象。
- 补充,为什么对象在初始化的时候,需要
self = [super init]? 其实也是等于调一下父类的init方法,把父类的初始化数据带过来,写入到当前类的内存空间里,再交给当前类的实例对象。