self和super區(qū)別
self
是關鍵字
-
代表當前方法的調(diào)用者
- 如果是類方法:代表當前類
- 如果是對象方法:代表當前類的對象
super
編譯器指令
[self message]和[super message]的實現(xiàn)
其實不管是self還是super真正調(diào)用的對象都是一樣的,只是查找方法的位置不一樣,self是從當前類結(jié)構(gòu)中開始查找,super是從父類中查找,但方法真正的接受者都是當前類或者當前類的對象
[self message]:
會轉(zhuǎn)化為objc_msgSend(id self,SEL _cmd)這個函數(shù),在當前類結(jié)構(gòu)中找到方法并且調(diào)用
[super message]
會轉(zhuǎn)化為id objc_msgSendSuper(struct __rw_objc_super *super, SEL op, …)
,對比[self message]這里除了函數(shù)名加了super以外,第一個參數(shù)由self變成了一個結(jié)構(gòu)體,下面讓我們來解開這個結(jié)構(gòu)體的真面目
struct __rw_objc_super {
struct objc_object *object; //代表當前類的對象
struct objc_object *superClass;
__rw_objc_super(struct objc_object *o, struct objc_object *s) : object(o), superClass(s) {}
};
1
2
3
4
5
這個結(jié)構(gòu)體中有兩個參數(shù):object的對象和一個superClass的結(jié)構(gòu)體指針,這里的object相當于上面的self
在執(zhí)行[super message]時,會做下面的事
- 編譯器會先構(gòu)造一個__rw_objc_super的結(jié)構(gòu)體
- 然后去superClass的方法列表中找方法
- 找到之后由object調(diào)用。
所以當你用[self Class]和[super Class]打印類的時候,打印的都是同一個類,因為他們只是查找方法的位置不同,但是調(diào)用方法的類/對象是一樣的.
為什要寫self = [super init]?
因為在Xcode中,你輸入init然后tab就會幫你補全這個方法,以至于我一直都忽略了為什么在[super init]之后還要賦值給self,然后進行判斷,其實這和類簇有關系,我們不能保證init的內(nèi)存和alloc出來的內(nèi)存是同一塊內(nèi)存,像NSString在alloc和init之后的對象分別是NSPlaceholderString和__NSCFConstantString*造成[super init]之后的內(nèi)存被改變,所以在[super init]之后是nil,因此我們不能保證alloc和init的是同一塊內(nèi)存,加上這樣的判斷是為了提高容錯性,如果init成功就返回對象,否則返回nil.