iOS [super class] vs [self class]

今天被大佬问了一个问题

// 下面的代码输出什么?
@implementation Son : Father
- (id)init
{
    self = [super init];
    if (self) {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
    return self;
}
@end

我一看,还挺简单的嘛,不就是SonFather嘛!
结果居然告诉我错了,我滴个天啊!赶紧查查看~~

结果如下:
原来 self 和 super 表面上在 调用同一个方法,但实际上并不一样。如ObjcRuntimeRef中所说:


iOS [super class] vs [self class]_第1张图片
Sending Message

self 调用的是 objc_msgSend(void /* id self, SEL op, ... */ )方法,其中第一个参数就为 self 本身。
而 super 调用的是 objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ )方法,其中第一个参数居然是一个结构体!
结构体内容如下:

struct objc_super {
    /// Specifies an instance of a class.
    __unsafe_unretained _Nonnull id receiver;
    /// Specifies the particular superclass of the instance to message. 
    __unsafe_unretained _Nonnull Class super_class;
};

其中 id 指的是当前类对象 self,super_class 指的是父类也就是 Father 类。

那么答案就清楚了,当使用 [self class] 时,这时的 self 是 Son,在使用 objc_msgSend 时,第一个参数是 receiver 也就是 self。第二个参数,要先找到 class 这个方法的 selector,先从 Son 这个类开始找,没有,然后到 Son 的父类 Father 中去找,也没有,再去 Father 的父类 NSObject 去找,一层一层向上找之后,在 NSObject 的类中发现这个 class 方法,而 NSObject 的这个 class 方法,就是返回 receiver 的类别,所以这里输出 Son。

当使用 [super class] 时,这时要转换成 objc_msgSendSuper 的方法。先构造 objc_super 的结构体吧,第一个成员变量就是 self,第二个成员变量是 Father,然后要找 class 这个 selector,先去 superClass 也就是 Father 中去找,没有,然后去 Person 的父类中去找,结果还是在 NSObject 中找到了。然后内部使用函数 objc_msgSend(objc_super->receiver, @selector(class)) 去调用,此时已经和我们用
[self class] 调用时相同了,此时的 receiver 还是 Son,所以这里返回的也是 Son。

终于可以安心睡觉了 (~﹃~)~zZ

你可能感兴趣的:(iOS [super class] vs [self class])