引用[blog.sunnyxx.com]大神的一道题
@implementation Son : Father
- (id)init {
self = [super init];
if (self) {
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
先说答案:都是Son
原因:[self class]没什么说的了,如果不理解请参考[做题系列1]。
至于[super class],它在编译后变成了
((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Son"))}, sel_registerName("class"));
好吧,我们来简化一下
objc_msgSendSuper({self, class_getSuperclass(objc_getClass("Son"))}, sel_registerName("class"));
看上去舒服多了,再看下objc_msgSendSuper的声明
d objc_msgSendSuper(struct objc_super *super, SEL op, ...)
以及objc_super结构体的声明
struct objc_super {
__unsafe_unretained id receiver;
__unsafe_unretained Class super_class;
};
这时我们注意到,objc_super结构体中的receiver还是self。
于是在运行时,从父类开始沿着继承链继续向上寻找class方法,最后在NSObject中找到,此时,[self class]与[super class]等价(如果不理解,请参考系列1中class源码)。
其实这里我有一些疑问,假设如下一份代码:
@interface ClassB : ClassA
- (void)test;
@end
@implementation ClassB
- (id)init
{
self = [super init];
if (self)
{
[self test];
[super test];
}
return self;
}
- (void)test
{
NSLog(@"this is ClassB");
}
@end
ClassA中也实现了test函数。这时[super test],编译后变成
objc_msgSendSuper({self, class_getSuperclass(objc_getClass("ClassB"))}, sel_registerName("test"));
按照网上的一些说法,在ClassA中找到了test函数,然后内部调用objc_msgSend(objc_super->receiver, @selector(class)),但是这里的receiver是self啊,self又是ClassB,那应该调用的是ClassB的test。为什么执行的是ClassA的test呢?求大神解答
更正:当使用 [super test]时。实际上调用的是objc_msgSendSuper,第一个参数objc_super有2个属性,一个指向当前类,而另外一个指向父类。当调用objc_msgSendSuper时,先去objc_super->super_class中找是否有test函数,若有,则调用,若没有,则继续去父类查找。而第一题中[super class]为什么会返回Son呢,先看- (Class)class的实现:
- (Class)class {
return object_getClass(self);
}
也就是说,无论我是用self还是用super,只要没被子类覆盖,那最终的都是要执行object_getClass(self),而这里被写死了self,也就是无论self还是super,结果都是objc_msgSend(self, @selector(class)) (注:当然super的时候是objc_msgSend(objc_super->receiver, @selector(class)))。所以结果都为Son。
以上仅为我个人猜测,因为我也不知道该如何验证,这是目前我能想的通的逻辑。若有大神可以从代码理论证明,烦请告知,感激不尽。
网友评论