2010-01-16 112 views
8

好吧,我有一種感覺,你們能夠快速指出爲什麼我對此感到困惑,但我有一個問題,爲什麼以下不會導致編譯器錯誤或警告:Objective-C類型推斷

NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ]; 

selectedObjectNSObject,和name恰好是int類型的@property的名稱。

什麼困擾我的是爲什麼編譯器是完全願意承擔的[ self.selectedObject valueForKey:name ]返回的結果是NSNumber *型(不帶類型轉換的話),以便與以integerValue調用鏈的消息。顯然,KVC將非對象「數字」類型封裝到NSNumber中,但編譯器無法知道-valueForKey:在此特定情況下將返回NSNumber *

爲什麼不會導致編譯器警告沿着「id」行可能不會響應「-integerValue」?

回答

10

我希望我說得對:這是因爲id是「特殊的」。 id類型的對象可以發送任何您想要的消息,編譯器不會執行檢查,並且會在運行時檢查所有內容。換句話說,id類型是Objective-C的「動態類型」部分,而所有其他類型(如NSObject)是「靜態類型」部分。

這樣,您可以選擇要使用靜態打字的位置以及要使用動態打字的位置。這是完全合法的,做這樣的事情:

id str1 = @"Hello"; 
id str2 = [str1 stringByAppendingString:@", world"]; 

但通常你輸入字符串「緊密」爲NSString S,因爲你得到編譯時靜態類型檢查的方便,只能求助於動態類型,其中靜態的會妨礙,就像valueForKey的情況。

+0

謝謝!我有一種感覺,它與'id'是Objective-C中的特權類型有關。 :)我的傾向是總是在任何可能的時候都緊緊打字,所以我想我從未遇到過這種看似奇怪的行爲。猜猜這使得'id'既強大又危險。我想知道在處理'id'的時候給類似的編譯器提供一些上下文是否更好,或者如果你對'id'將會變成什麼會產生積極的影響(如我的例子中的情況那樣) 。 – LucasTizma 2010-01-16 08:36:42

+0

大拇指的規則是:「儘可能靜態輸入,需要時動態輸入。」(您可以通過谷歌獲得更多信息。)在這種情況下,我不會強制轉換,它只會使表達式難以閱讀。有時候你必須註釋以幫助編譯器選擇正確的方法 - 請參閱http://stackoverflow.com/questions/1113270。 – zoul 2010-01-16 08:52:10

+0

感謝您的鏈接。我遇到了一些令人討厭的小錯誤,這是由於方法命名導致與現有SDK方法名稱「衝突」的結果。認爲編譯器對我很瘋狂。 :)是的,我完全支持「儘可能靜態打字,需要時動態打字」的理念。現在,如果只有Objective-C會添加對類型化集合的支持......看起來往往不是,我知道我的集合將要存儲什麼。 – LucasTizma 2010-01-16 09:08:39