先來(lái)看一個(gè)經(jīng)典面試題:
以下代碼輸出什么?
// 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
答案是兩個(gè)NSLog輸出完全一樣,都是 Son鸯旁。這道面試題就是考察self
和super
的區(qū)別與聯(lián)系。第一個(gè)NSLog輸出Son肯定是不用說(shuō)的。第二個(gè)輸出中泣港,[super class]
輸出Son就要說(shuō)說(shuō)self
和super
到底有什么小曖昧??
self
self
是一個(gè)隱藏參數(shù)變量這個(gè)指針指向當(dāng)前調(diào)用方法的對(duì)象(即
receiver
)self
調(diào)用自己方法-
self
調(diào)用方法:- 當(dāng)使用
self
調(diào)用方法時(shí),會(huì)首先從當(dāng)前類的方法列表中開始尋找价匠,如果沒(méi)有再去父類中尋找爷速; - 當(dāng)使用
self
調(diào)用方法時(shí),runtime會(huì)將其轉(zhuǎn)化為objc_msgSend
函數(shù):
objc_msgSend(id receiver, SEL selector, ...)
第一個(gè)參數(shù)是消息接收者霞怀,第二個(gè)參數(shù)是調(diào)用的具體方法的selector
惫东,后面是selector
方法的可變參數(shù)。
- 當(dāng)使用
super
super
并不是隱藏參數(shù)毙石,只是編譯器的指令符號(hào)super
調(diào)用父類方法-
super
調(diào)用方法:- 當(dāng)使用
super
調(diào)用方法時(shí)廉沮,從父類的方法列表中開始找,然后調(diào)用父類的這個(gè)方法徐矩。 - 當(dāng)使用
super
調(diào)用方法時(shí)滞时,runtime會(huì)將其轉(zhuǎn)化為objc_msgSendSuper
函數(shù):
objc_msgSendSuper(struct objc_super *super, SEL op, ...)
第一個(gè)參數(shù)是個(gè)objc_super
的結(jié)構(gòu)體,第二個(gè)參數(shù)還是類似objc_msgSend
方法的selector
滤灯。而objc_super
的結(jié)構(gòu)體如下:
struct objc_super { __unsafe_unretained _Nonnull id receiver; __unsafe_unretained _Nonnull Class super_class; };
- 當(dāng)調(diào)用
[super class]
時(shí)坪稽,會(huì)被轉(zhuǎn)換為下面的代碼:
struct objc_super objcSuper = { self, class_getSuperclass([self class]) }; id (*sendSuper)(struct objc_super*, SEL) = (void*)objc_msgSendSuper; sendSuper(&objcSuper, @selector(class));
- 當(dāng)使用