2012-12-15 60 views
2

新增目標-c。編寫了一段代碼片段以更好地理解init機制,並最終提出了一些問題。Objective-c - [super init]返回什麼?

@implementation MyClass  
    -(id) init 
    { 
     if (self) { 
      i = 5; 
      NSLog(@"self before init - %@ %p i=%d",[self className], &self, i); 
     } else { 
      NSLog(@"self is null???"); 
     } 

     id someClass = [super init]; 
     NSLog(@"the result of super-init - %@ %p",[someClass className], &someClass); 

     self = [super init]; 
     if (self) { 
      NSLog(@"self after init - %@ %p %d",[self className], &self, i); 
     } else { 
      NSLog(@"self is null???"); 
     } 

     return self; 
    } 

i是私有實例變量int

下面是結果:

2012-12-14 18:01:26.403 Init[1621:303] self before init - MyClass 0x7fff5fbff848 i=5 
2012-12-14 18:01:26.405 Init[1621:303] the result of super-init - MyClass 0x7fff5fbff838 
2012-12-14 18:01:26.405 Init[1621:303] self after init - MyClass 0x7fff5fbff848 5 

真正讓我吃驚的是,那SomeClass的類名是MyClass

  • NSObject如何知道返回子類實例(不只是類型匹配,它是完全相同的對象)?

我知道,這是不好的形式調用init很多次,並呼籲init前初始化實例變量,但我只是嘗試。

謝謝。

+1

您不應該使用'&someClass' - 它返回引用的地址,而不是引用包含的內容。使用'someClass'。 – nielsbot

+0

'''-init'在'+ [ alloc]'的結果上被調用,當然這返回一個(未初始化的)實例......'-init'不會進行分配。 – nielsbot

+0

@nielsbot說的是真的 - 你打印的地址是指針變量的地址,而不是變量指向的對象的地址。這可能會造成一些混淆。 –

回答

2

您確實需要使用標準schemen(或多或少):

-(id)init { 
    self = [super init]; 
    if (self) { 
     // Do initialization stuff 
    } 
} 

你的類的子類的一些其他類。對super init的調用運行超類的init例程。沒有它,你的班級沒有正確初始化,可能會出現奇怪的故障。 (然而,這可能不是明智的調用super init兩次,因爲這可能有不良的副作用。)

有,你不會把super init案件,但在自己的類會改爲調用一個版本的init。基本上,如果您有initWithJunk:init,您可以撥打initWithJunk:而不是[super init],這樣self init就可以完成,並且不需要在initWithJunk:中進行復制。

如果您編寫一個將init...方法添加到現有類的「類別」,那麼這尤其重要 - 您必須調用某個版本的[self init]以確保基類的初始化器運行。

記者瞭解到,super init方法不是(通常)與更換新現有實例,而是初始化它實例字段屬於超。之所以從super init呼叫接收的「自我」值後面是兩方面:

  1. 初始化過程可以返回在某種錯誤的發生,則一個nil
  2. 在一些(罕見的)特殊情況下,init例程可能會使用不同的例程(例如緩存版本)替換提供的實例。
相關問題