先从一段代码说起:
@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方法,把父类的初始化数据带过来,写入到当前类的内存空间里,再交给当前类的实例对象。