一电谣、self
和 super
區(qū)別
-
self
是類(lèi),super
是預(yù)編譯指令(就是給編譯器看的抹蚀,不是一個(gè)指針; 只要編譯器看到這個(gè)標(biāo)志剿牺,就會(huì)讓當(dāng)前對(duì)象去調(diào)用父類(lèi)的方法,本質(zhì)還是當(dāng)前對(duì)象在調(diào)用) -
self
調(diào)用自己方法环壤,super
是調(diào)用父類(lèi)方法 -
[self class]
和[super class]
輸出是一樣的(重寫(xiě)了就不一樣了)
二晒来、self
和 super
底層實(shí)現(xiàn)原理
- 當(dāng)使用
self
調(diào)用方法時(shí),會(huì)從當(dāng)前類(lèi)的方法列表中開(kāi)始找郑现,如果沒(méi)有湃崩,就從父類(lèi)中再找;
當(dāng)使用super
時(shí)接箫,則從父類(lèi)的方法列表中開(kāi)始找攒读,然后調(diào)用父類(lèi)的這個(gè)方法。 - 當(dāng)使用
self
調(diào)用時(shí)辛友,會(huì)使用objc_msgSend
函數(shù):id objc_msgSend(id theReceiver,SEL theSelector, ...)
第一個(gè)參數(shù)是消息接收者薄扁,第二個(gè)參數(shù)是調(diào)用的具體類(lèi)方法的selector
剪返,第三個(gè)參數(shù)是selector
方法的可變參數(shù)。
(以:[self setName:]
為例分析:
a: 編譯器會(huì)替換成調(diào)用objc_msgSend
的函數(shù)調(diào)用邓梅,
b: 其中theReceiver
是self
脱盲,theSelector
是@selector(setName:)
,這個(gè)selector
是從當(dāng)前self
的class
的方法列表開(kāi)始找的setName
日缨,
c: 當(dāng)找到后把對(duì)應(yīng)的selector
傳遞過(guò)去钱反。) - 當(dāng)使用
super
調(diào)用時(shí),會(huì)使用objc_msgSendSuper
函數(shù):id objc_msgSendSuper(struct objc_super *super,SEL op, ...)
第一個(gè)參數(shù)是個(gè)objc_super
的結(jié)構(gòu)體匣距,
第二個(gè)參數(shù)還是類(lèi)似上面的類(lèi)方法的selector
struct objc_super {
id receiver;
Class superClass;
};
(以: [super setName:]
為例分析:
a: 構(gòu)建 objc_super
的結(jié)構(gòu)體面哥,此時(shí)這個(gè)結(jié)構(gòu)體的第一個(gè)成員變量 receiver
就是子類(lèi),和 self
相同墨礁。而第二個(gè)成員變量 superClass
就是指父類(lèi)調(diào)用 objc_msgSendSuper
的方法幢竹,將這個(gè)結(jié)構(gòu)體和 setName
的 sel
傳遞過(guò)去
b: 函數(shù)里面在做的事情類(lèi)似這樣:從 objc_super
結(jié)構(gòu)體指向的 superClass
的方法列表開(kāi)始找 setName
的 selector
,找到后再用 objc_super
結(jié)構(gòu)體的 receiver
去調(diào)用這個(gè) selector
)
三恩静、為什么要 self = [super init];
符合 objective-c 繼承類(lèi)初始化規(guī)范焕毫, super
同樣也是這樣。
self = [super init]
中的 [super init]
是去 self
的 super
中調(diào)用 init
驶乾,而 super
還會(huì)繼續(xù)調(diào)用 super
的 super
的 init
邑飒, 直到根類(lèi) NSObject 中的 init
。
根類(lèi)中 init
負(fù)責(zé)初始化內(nèi)存區(qū)域级乐, 向里面添加 一些必要的屬性疙咸,返回內(nèi)存指針,這樣, 延著繼承鏈初始化的內(nèi)存指針會(huì)被從上到下傳遞风科,在不同的子類(lèi)中向塊內(nèi)存添加子類(lèi)必要的屬性撒轮,直到使用的本類(lèi)中得到內(nèi)存指針,賦值給 slef
參數(shù)贼穆。
四题山、class
、superClass
區(qū)別
class
獲取當(dāng)前方法調(diào)用者的類(lèi)
superclass
獲取當(dāng)前方法調(diào)用者的父類(lèi)
#import "Son.h"
@interface Son : Person
@end
@implementation Son
- (instancetype)init {
self = [super init];
if (self) {
NSLog(@"%@", NSStringFromClass([self class])); // 獲取當(dāng)前方法調(diào)用者的類(lèi) (Son)
NSLog(@"%@", NSStringFromClass([super class])); // 本質(zhì)還是當(dāng)前方法調(diào)用者 (Son)
NSLog(@"%@", NSStringFromClass([self superclass])); // 當(dāng)前方法調(diào)用者的父類(lèi) (Person)
NSLog(@"%@", NSStringFromClass([super superclass])); // 當(dāng)前方法調(diào)用者的父類(lèi) (Person)
}
return self;
}
@end