我也说说runtime的一道经典面试题

####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。

不对的地方请指正,欢迎拍砖。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值