Demo
从经典的一个demo开始 。前提:XXSon
继承自 XXFather
。
@implementation XXSon
- (id)init
{
self = [super init];
if (self)
{
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
打印结果都是 XXSon。
分析
准备工作
- 我们知道向对象发送消息最终会转化成objc_msgSend方法,定义如下:
objc_msgSend(void /* id self, SEL op, ... */ )
第一个参数是接收消息的对象
第二个参数是方法选择器
-
super
关键字接受消息时,会转化成objc_msgSendSuper方法,定义如下
objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ )
第一个参数是objc_super
结构体
第二个参数是方法选择器
objc_super
结构体的定义在 message.h
文件中, 现在都是OBJC2,简化后定义如下:
/// Specifies the superclass of an instance.
struct objc_super {
/// Specifies an instance of a class.
__unsafe_unretained _Nonnull id receiver;
__unsafe_unretained _Nonnull Class super_class;
/* super_class is the first class to search */
};
super
关键字表示让直接从super_class
中开始查找方法的实现。
- Demo中的XXSon.m经过
clang -rewrite-objc XXSon.m
编译后的.cpp文件之后的相关代码是:
static id _I_XXSon_init(XXSon * self, SEL _cmd) {
self = ((XXSon *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("XXSon"))}, sel_registerName("init"));
if (self)
{
NSLog((NSString *)&__NSConstantStringImpl__var_folders_4c_2bxyjsn12ggc69ffj64bxvbc0000gn_T_XXSon_089961_mi_0, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"))));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_4c_2bxyjsn12ggc69ffj64bxvbc0000gn_T_XXSon_089961_mi_1, NSStringFromClass(((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("XXSon"))}, sel_registerName("class"))));
}
return self;
}
结果分析
- 调用
[self class]
会转换成objc_msgSend(self, @selector(class))
其receiver
为self
。调用class
方法,因XXSon
并未定义class
方法,所以会从其父类XXFather
中查找,XXFather
中也未定义,会再从其父类NSObject
中查找。NSObject
中的class
方法会调用object_getClass()
,object_getClass()
的定义在objc-class.mm
文件中,具体如下:
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
[self class]
的receiver
为self
,所以object_getClass
这里的参数obj
就是self
。直接返回self
的isa
即 XXSon
。
- 调用
[super class]
,会转化成objc_msgSendSuper
, 同时会自动生成struct objc_super *super
。objc_super->receiver
为self
(从.cpp文件中就可以看出来),objc_super-> super_class
为XXFather
。所以直接从XXFather
中查找class
方法,在NSObject
中找到class
方法。最后调用objc_msgSend(objc_super->receiver, @selector(class))
, 此时object_getClass()
方法的receiver
为objc_super->receiver
(即self
)。 所以和[self class]
的打印一样。
网友评论