先来看一个经典面试题:
以下代码输出什么?
// Son.h
#import "Father.h"
@interface Son : Father
@end
// Son.m
#import "Son.h"
@implementation Son
- (instancetype)init
{
self = [super init];
if (self) {
NSLog(@"%@",[self class]);
NSLog(@"%@",[super class]);
}
return self;
}
@end
答案是两个NSLog输出完全一样,都是 Son。这道面试题就是考察self
和super
的区别与联系。第一个NSLog输出Son肯定是不用说的。第二个输出中,[super class]
输出Son就要说说self
和super
到底有什么小暧昧
self
self
是一个隐藏参数变量这个指针指向当前调用方法的对象(即
receiver
)self
调用自己方法-
self
调用方法:- 当使用
self
调用方法时,会首先从当前类的方法列表中开始寻找,如果没有再去父类中寻找; - 当使用
self
调用方法时,runtime会将其转化为objc_msgSend
函数:
objc_msgSend(id receiver, SEL selector, ...)
第一个参数是消息接收者,第二个参数是调用的具体方法的selector
,后面是selector
方法的可变参数。
- 当使用
super
super
并不是隐藏参数,只是编译器的指令符号super
调用父类方法-
super
调用方法:- 当使用
super
调用方法时,从父类的方法列表中开始找,然后调用父类的这个方法。 - 当使用
super
调用方法时,runtime会将其转化为objc_msgSendSuper
函数:
objc_msgSendSuper(struct objc_super *super, SEL op, ...)
第一个参数是个objc_super
的结构体,第二个参数还是类似objc_msgSend
方法的selector
。而objc_super
的结构体如下:
struct objc_super { __unsafe_unretained _Nonnull id receiver; __unsafe_unretained _Nonnull Class super_class; };
- 当调用
[super class]
时,会被转换为下面的代码:
struct objc_super objcSuper = { self, class_getSuperclass([self class]) }; id (*sendSuper)(struct objc_super*, SEL) = (void*)objc_msgSendSuper; sendSuper(&objcSuper, @selector(class));
- 当使用