文章目錄
- [Obj-C筆記] "self = [super init]"的解釋與潛藏bug
[Obj-C筆記] "self = [super init]"的解釋與潛藏bug
Objective-C的推薦init方法寫法如下:
- (id) init{ if(self = [super init]) { //為子類增加屬性進行初始化 } return self;}
這裡涉及了幾個問題,
1. [super init]的作用:
物件導向的體現,先利用父類的init方法為子類執行個體的父類部分屬性初始化。
2. self 為什麼要賦值為[super init]:
簡單來說是為了防止父類的初始化方法release掉了self指向的空間並重新alloc了一塊空間。這時的話,[super init]可能alloc失敗,這時就不再執行if中的語句。
3. super作為訊息接受者的實質:
super並不是真正的指標,[super message]的實質是由self來接受父類的message。需要注意的是,[super message]中,message方法出現的self為[super message]語境中的self,即子類執行個體。
潛藏的bug:
假設有父類AObj與子類BObj。
當AObj的init方法如下:
- (id) init{ id tmp = self; self = [AObj alloc]; [tmp release]; //other staffs return self;}
BObj的init方法如下:
- (id) init{ if(self = [super init]) { //other staffs } return self;}
這時編譯能通過,但當BObj的執行個體使用到BObj擴充的屬性時,就會出現一個執行階段錯誤。錯誤的原因在於AObj的init方法用[AObj alloc]重新獲得了一塊僅僅適合存放AObj執行個體的空間。而BObj的init方法以為這是塊適合存放BObj的空間。當試圖讀寫BObj的擴充屬性時便會產生執行階段錯誤。
因此,當init方法需要重新alloc一塊空間時,正確的寫法如下:
- (id) init{ id tmp = self; self = [[self class] alloc]; [tmp release]; //other staffs return self;}
注意[self class]將獲得self指向的執行個體對應的類執行個體,本例中便是BObj。這樣AObj的任何子類的init方法都能保證安全了。