2010-05-15 53 views
12

調用一個構造函數假設您有以下兩個構造函數:Objective-C的 - 從另一個

- (id)initWithTitle:(NSString *)title; 
- (id)initWithTitle:(NSString *)title page:(NSString *)page; 

第二個構造是從第一沒有什麼不同,不同之處在於它樹立成員變量「頁」。

由於它基本上必須做同樣的事情,有沒有辦法從第二個調用第一個來減少代碼重複,或者您是否需要設置第三個方法來執行常見任務?

我談論一些與此類似,但我懷疑這會工作:

- (id)initWithTitle:(NSString *)_title { 
    if(self = [super init]) { 
     self.title = _title; 
    } 

    return self; 
} 

- (id)initWithTitle:(NSString *)_title page:(NSString *)_page { 
    if(self = [self initWithTitle:_title]) { 
     self.page = _page; 
    } 

    return self; 
} 
+2

@phunehehe有一個更好的解決方案,但是你發佈的*將*工作。 – 2010-05-15 14:30:37

+0

呵呵,我猜想現在我想到了。謝謝 – synic 2010-05-15 14:54:55

+5

越快放棄C++術語並開始使用Objective-C術語,文檔越早開始有意義。 Objective-C沒有構造函數或成員變量。它有初始化器和實例變量。 – bbum 2010-05-15 15:56:03

回答

18

,因爲我想這

- (id)initWithTitle:(NSString *)_title { 
    return [self initWithTitle:_title page:nil]; 
} 

- (id)initWithTitle:(NSString *)_title page:(NSString *)_page { 
    if(self = [super init]) { 
     self.title = _title; 
     self.page = _page; 
    } 
    return self; 
} 

隱而不宣的什麼你說是怪異」它的工作?

+0

這很完美。謝謝! – synic 2010-05-15 14:27:21

21

首先,你不必構造函數,你有兩個初始化:

- (id)initWithTitle:(NSString *)title; 
- (id)initWithTitle:(NSString *)title page:(NSString *)page; 

與大多數初始化,目標是設置一些實例變量(不是成員變量)。

第一步是確定您指定的初始化程序。你的情況,則可能是:

- (id)initWithTitle:(NSString *)title page:(NSString *)page; 

這意味着,正如其他人所描述- (id)initWithTitle:(NSString *)title;將實施:

- (id)initWithTitle:(NSString *)_title { 
    return [self initWithTitle:_title page:nil]; 
} 

不過,我會建議對這種模式,因爲它使子類更多的錯誤不是容易它應該是。在子類化過程中,您必須始終覆蓋指定的初始化程序您必須實現一個調用指定初始化程序的新初始化程序。很明顯,你擁有的初始化程序越多,在子類化中可能會引入的bug越多。

而且,這樣的:

Foo *f = [[Foo alloc] initWithTitle: @"Foo!" page: nil]; 

比這更清楚:

Foo *f = [[Foo alloc] initWithTitle: @"Foo!"]; 

第一個表示很特別,你有想過page,決定明確地將其設置爲nil或以其他方式依靠類Foo合理設置頁面。第二個沒有提供這樣的指示。

子類化和明確的意圖表示都是你在Cocoa中找不到這種便捷方法的主要原因(有些但大部分都比較陳舊 - 比政策真正成爲規則時還要舊)。

+2

當您創建一個引入新初始化程序的類別時,您無法避免該模式,而只需調用現有的初始化程序。 – 2012-08-17 18:24:46