2010-06-03 58 views
3
// A : Parent 
@implementation A 
-(id) init 
{ 
    // change self here then return it 
} 
@end A 

A *a = [[A alloc] init]; 

a。只是想知道,如果自我是一個局部變量或全球?如果它是本地的,那麼initself = [super init]的點數是多少?我可以成功地定義一些局部變量並像這樣使用,爲什麼我需要將它分配給self是超級本地變量嗎?

-(id) init 
{ 
    id tmp = [super init]; 
    if(tmp != nil) { 
     //do stuff 
    } 
    return tmp; 
} 

b。如果[super init]返回一些其他對象實例,我不得不覆蓋self,那麼我將無法再訪問A的方法,因爲它將是完全新的對象?我對嗎?

c。 superself指向相同的內存,它們之間的主要區別是方法查找順序。我對嗎?

對不起,沒有Mac的嘗試,學習理論爲現在...

回答

5

Dreamlax的答案是正確的...但澄清可能會有所幫助。

a。只是想知道,如果自己是本地的 變量或全球?如果它是本地然後 init中的self = [super init]是什麼意思?我可以成功地 定義一些局部變量,並使用這樣的 ,爲什麼我需要將它自己分配給 。

self不是局部變量。這是方法調用的一個參數。事實上,第一個論點。第二個參數是_cmd,即正在執行的方法的選擇器的名稱。

self的特別之處在於編譯器使用self來訪問實例變量。也就是說,如果你說self = [super init]和超類的init碰巧返回不同的東西,任何進一步的實例變量訪問仍然是正確的。

b。如果[超級初始化]返回一些其他的 對象實例,我不得不 覆蓋自我然後我將不能 訪問A的方法,因爲 它將是完全新的對象?我是 對不對?

如果超的init回報的東西,是與A不兼容的一個實例,然後事情已經在超設計了可怕的歪曲。請記住Objective-C是完全動態的。因此,沒有任何理由,超級的init返回的實際上需要是A的實例,但它更好的行爲就像A。現在,它可能是A的一個子類的全新實例,因此,所有A的方法都可以正常工作。

在行間讀取;請記住Objective-C是完全動態的。沒有靜態方法調度這樣的事情。對象的類可以隨時更改,只要新類響應方法,任何隨機方法調用都將繼續工作。並不是說這實際發生在運行時,只是它可能

c。超級和自己指向相同的 內存,它們之間的主要區別 是方法查找順序。 我對不對?

現在,這是一個有趣的問題。 super並不真正指向任何東西。對於所有的意圖和目的,super可以被視爲在這一點的魔術。也就是說,當編譯器將super視爲方法調用的目標時,它將其編譯爲略微不同的調用站點,調用其中一個objc_msgSendSuper()變體,正如名稱所暗示的那樣 - 有效地「搜索」該方法在編寫呼叫的類別的父類別中開始實施。

2
  1. 自我是提供給方法實現的參數。所有Objective-C實例和類方法在方法的參數之前都有兩個隱式參數。隱含的參數是self_cmd_cmd是用於確定方法實現的選擇器。

  2. 如果super返回一個不同類的實例,那麼情況就是這樣,但它也有可能返回同一類的不同實例。

  3. super是一個關鍵字,而不是一個變量。它通知編譯器使用一個不同的運行時函數,該函數在比當前類更高的一個類上開始方法解析。

+0

謝謝,但完全沒有回答第一個問題 - 爲什麼我需要'self = [super init]',並且不能使用任何本地變量來完成這項工作。 – Pablo 2010-06-03 02:11:52

+0

@Michael:因爲您需要調用您的超類的初始化程序,並且因爲您的超類的初始化程序(或其超類的初始化程序)可能會返回一個不同的實例;如果你沒有改變自我,那麼你將不會初始化正確的實例,並且你還會將錯誤的實例返回給你的初始者。一個超類的初始化者返回一個不同的實例是非常非常罕見的,所以很多人可以自由決定是否將'[super init]的結果分配給'self',但我個人總是這麼做。這是一種語言的成語。 – dreamlax 2010-06-03 02:17:12

+0

我不明白的是「自我」真正改變的地步。如果'self'是一個參數,那麼它是通過引用傳遞的,所以當我改變它時,原始值也會被改變?否則,如果在返回後發生更改,在'init'之外,當我實例化'A'時,那麼我可以使用'tmp' var來完成它。 – Pablo 2010-06-03 02:23:36