self.class 和 super.class 的区别

一道很经典的面试题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@interface DemoObj : NSObject
@end
@implementation DemoObj
- (instancetype)init {
self = [super init];
if (self) {
Class sClass = self.class;
NSLog(@"self.class: %@",sClass);
Class spClass = super.class;
NSLog(@"super.class: %@",spClass);
}
return self;
}
@end

分别打印什么?初看以为前者打印DemoObj,后者打印NSObject,实则不然,两者均是打印DemoObj。这是为什么呢?

Xcode - Debug - Debug Workflow - Always Show Disasembly 。通过这个操作,在第二句NSLog之后,打上断点,之后运行时,可以看到以下两个截图。

1

2

毫无疑问,self.class 实则是通过 objc_msgSend 进行发送消息,最后得到的是该类的类名。但是 super.class 使用的却是 objc_msgSendSuper2,并不是我们认为的 objc_msgSendSuper。通过查询runtime源码。可以得知 objc_msgSendSuper2 定义。

1
2
3
4
// objc_msgSendSuper2() takes the current search class, not its superclass.
OBJC_EXPORT id _Nullable
objc_msgSendSuper2(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)
OBJC_AVAILABLE(10.6, 2.0, 9.0, 1.0, 2.0);

文档解释的很清楚。调用的是当前类,并不是其父类。