2012-03-04 83 views
3

我偶然發現了這個帖子In Objective-C why should I check if self = [super init] is not nil?自我= [超級初始化]再訪

我能理解this syntax

- (id)initWithString:(NSString *)aString 
{ 
    self = [super init]; 
    if (self) 
    { 
     instanceString = [aString retain]; 
    } 
    return self; 
} 

this syntax

- (id)init; 
{ 
if (!(self = [super init])) 
    return nil; 

// other stuff 
return self; 
} 

,但我還是不明白「標準」模板語法

- init { 
    if((self = [super init])) { 
     // set up instance variables and whatever else here 
    } 
    return self; 
} 

有人可以儘可能清楚地告訴(3)與(1)或(2)相比,或多或少有什麼作用?我讀過的所有內容都很混亂(爲什麼人們不能同意純粹技術的東西看起來像政治:))

不過,當我閱讀作者的文章,並且我可以模糊地理解它,遠遠超出了僅僅是語法糖辯論或品味的問題。例如it is said

奇怪然後,當殼體3是壓倒性多見,支持1,2和4,但不兼容與殼體3已經成爲standard.Curiously然後初始化,而殼體3是壓倒性更常見,支持1,2和4但與情況3不兼容的初始化器已成爲標準。

因此,如果可能的話,我想從Objective C Gurus得到一個深刻的哲學答案。

回答

5

來理解的關鍵(3)是,如果線

if((self = [super init])) { 

在C中,每個運營商有返回值,你根本不必使用它。因此,就像3 + 4返回7一樣,運算符=返回剛分配的相同值。這允許你做有趣的事情是這樣吧:

int a, b, c, d; 

a = b = c = d = 5; 

(這工作,因爲運營商有從右到左結合這意味着a = b = 3;相當於a = (b = 3);所以b設置爲三個第一,然後。 a設置爲相同的值。)

所以,現在我們可以看到測試

if((self = [super init])) { 

是完全一樣的

self = [super init]; 
if (self) { 

他們都做同樣的事情,雖然。至於首選方案,很多人認爲把表達式放入if語句是不好的做法,因爲如果你不習慣它,很難注意到。蘋果似乎已經與你在他們的模板中列出的第一個例子中解決,還添加了一個編譯器第一次警告,如果您嘗試做沒有愚蠢的雙括號if(())

+0

至於你關於Cocoa with Love的問題,我相信他在談論罕見的情況,其中'[super init]'返回超類的單例實例,在這種情況下,他不想重寫實例變量目的。就我而言,這更像是一種學術上的好奇心,而不是你需要擔心的任何事情。 – joerick 2012-03-04 11:49:27

+0

謝謝我現在更好地理解3的語法,所以我給你正確的答案,因爲這是我首先提出的問題。儘管如此,他認爲[超級初始化]可以返回4個案例,而語法3只能處理3個案例,而不處理可能相當頻繁的第四個案例。所以這不是品味的問題:這是一個考慮到所有例外的問題,否則你的應用程序不健壯,你不同意嗎? – user310291 2012-03-04 13:21:03

+0

在Cocoa中這是一個非常罕見的情況,你想要繼承這些會導致問題的對象之一。這些示例是類集羣或單例對象。至少,我可以想到沒有理由繼承一個單身人士,而不用另外引用單身人士。至於繼承類集羣,通常在Cocoa中,我們更喜歡[對象組合](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html# // apple_ref/doc/uid/20000154-397934),而不是繼承。 – joerick 2012-03-04 13:35:06

5

所有這三個完成完全相同的任務:調用[super init],將它分配給self(如果super的init返回不同的對象,在某些情況下可能),並測試返回的指針是否爲零。如果它是零,則不做任何事情。

示例#1和#3是相同的,它們的語法稍微重新排列。 #2不同之處在於它返回一個明確的值nil,而#1和#3隱含地這樣做。

哪個使用是一個味道的問題。我更喜歡#2,因爲它保存了一個凹痕級別(如果可能,我喜歡避免凹痕,因爲如果你深入縮進了四五級,它確實很難跟上流程)。

人們並不普遍認同哪一個使用的理由完全一樣,他們不同意使用哪種縮進方式(K & R,Allman,GNU,Whitesmith,...):這是個人偏好,並沒有改變邏輯。

+0

當我讀到作者的文章,其意義遠遠超出了只是語法糖或例如據說這裏的味道:)事項:「奇怪的話,同時案件3絕大多數是比較常見的,支持初始化1,2和4,但是不相容的與殼體3已經成爲standard.Curiously然後,當殼體3是壓倒性多見,支持1,2和4,但不兼容與殼體3已經成爲標準初始化「。 – user310291 2012-03-04 11:28:34

+0

@ user310291:三個變種你引用的所有支票'nil',但是從你所引用的文章段落是關於什麼的'[超級初始化]'可以退貨。你所引用的三種變體在這裏的表現完全相同。爲了「解決」這個問題,作者提出了一個新的變體,它將'[super init]'的返回值存儲在一個變量中,並將其與(仍然不變)'self'進行比較。所以對於你所引用的三種變體,它真的*是一種味道和語法問題。他們都表現完全一樣。 – DarkDust 2012-03-04 12:32:13

+0

他認爲[超級初始化]可以返回4個案例,而語法3只能處理3個案例,而它不能處理可能相當頻繁的第四種情況。所以這不是品味的問題:這是一個考慮到所有例外的問題,否則你的應用程序不健壯,你不同意嗎? – user310291 2012-03-04 13:20:21

1

如果你有一個變量並沒有==,!=,>或類似的東西表達的將是真正的,如果你的變量(在這種情況下,一個指向對象)不爲0,這意味着,如果你的指針唐沒有指向任何東西。零和NULL爲0定義的,所以你可以寫

if ((self = [super init]) != nil) {} 

if ((self = [super init]) != NULL) {} 

if ((self = [super init]) != 0) {} 

或者乾脆

if ((self = [super init])) {} 

了。

+1

非常感謝,非常清楚,我不能投票第二個好答案:) – user310291 2012-03-05 20:14:42

0

我也喜歡額外的「房間」使用過於冗長通過提供,很少直觀......坦白地說醜陋語法我在蘋果公司的代碼見/城鎮周圍,等...

-(id) init { if (self != super.init) return nil; ... 

我可能是溺水的嬰兒 - 並導致老帥哥印度人在這個過程中哭 - 但我只是堅持這一切一行 ...和記得return self; AOK爲止!