赞
踩
####iOS程序猿,一定见过下面这道面试题:
@implementation Son : Father
- (id)init
{
self = [super init];
if (self)
{
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
输出结果:
2017-08-09 20:46:25.013 runtime第一讲[1797:403669] Son
2017-08-09 20:46:25.013 runtime第一讲[1797:403669] Son
给super发消息,不应该输出Father么?按照我的步骤往下看,你马上就能明白这个问题。
####第一步:clang -rewrite-objc 路径/Son.m
####第二步:找到执行NSLog的代码,如下图所示:
####第三步:这两个NSLog方法有什么不同呢,分析如下:
第一个NSLog可简化为:
objc_msgSend((id)self, set_registerName("class"))
显然class消息的接受者是self,也就是Son实例。
第二个NSLog可简化为:
objc_msgSendSuper(__rw_objc_super, set_registerName("class"))
__rw_objc_super
是什么东西?
哦,__rw_objc_super
是一个结构体,它用来干什么?这么问没意义,你应该问这个结构体在objc_msgSendSuper方法里用来干什么?
根据苹果文档可知:__rw_objc_super
结构体用来储存要接收消息的类的实例(Son),以及开始搜索方法实现的超类(Father)。
所以,objc_msgSendSuper接收消息的实际上是son,但它是从father类开始搜索class方法,由于father类并没有重载class方法,所以两次都是执行的NSObject的class方法。
所以,输出相同的Son。
不对的地方请指正,欢迎拍砖。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。