2011-08-26 100 views
0

我來自C#背景,我正在學習Objective-C。我想知道我是否可以對語法做一些澄清。在此先感謝您的幫助。objective c 2.0 - 關鍵字鑄造與非關鍵字鑄造

下面顯示的代碼行之間有什麼區別?鑑於我肯定知道,在 「tempItem」 字典類型是(的NSString *)類型和newsItem.pictureUrl也是(的NSString *):

方案1:

newsItem.pictureUrl = [tempItem objectForKey:@"picture"]; 

方案2:

newsItem.pictureUrl = (NSString *)[tempItem objectForKey:@"picture"]; 

回答

3

我知道你的意思。我也開始喜歡投,因爲它清楚地表明你在做什麼。但過了一段時間,它變得非常乏味,你學會忽略它。

事實上,沒有泛型,容器只存儲對象,這有點令人失望,特別是如果你來自泛型語言。這意味着你不斷地,明確地在對象和簡單類型(例如NSNumber和int之間)之間進行轉換,並且除了查詢[object class]外,沒有辦法確保只獲得NSString或可以處理的異常。

但演員陣容不會有任何區別。如果返回的對象不是NSString,並且將其轉換爲一個,則不會產生任何影響。演員沒有隱式類型檢查,也沒有轉換。它只是重新解釋了返回值。

0

Objective-C實例的類型實際上僅用於確定爲創建實例以及靜態分析(代碼完成,編譯等)而分配的適當內存量。在運行時,實例全部由ID的表示,並且對象的實際類型意味着更少。這種動態行爲是通過設計的,並且在設計ObjC應用程序時可以提供很大的靈活性。

在典型的ObjC程序中,您將看到很少的類型轉換。

1

對象類型間的轉換基本上可以隻影響兩件事情:

  1. 什麼警告編譯器發出(如「此變量的類沒有出現有你想調用的方法」 )

  2. 的對象有哪些屬性以及它們如何工作(如self.awesome相當於吸氣可能是[self awesome][self isAwesome]

它強調不會影響你得到什麼樣的對象。編譯時的靜態類型只是編譯器的提示。如果你將一個對象轉換成它不是的類型,那麼你只是對編譯器說謊。

在這種特殊情況下,它根本沒有任何效果。有些人會這樣寫代碼,但是AFAIK僅僅是因爲他們覺得很安慰,就像他們使用靜態類型語言一樣(即使Objective-C不是)。

0

只有當您希望讓編譯器瞭解某個調用的類型時,鑄造纔是真正必要的,以便它不會給出「可能不會迴應」的警告。

1

這兩行代碼之間沒有區別;它純粹是文體。

這裏的方法objectForKey:返回一個類型爲id的對象,它是一個通用對象指針。在Objective-C中,id可以隱式轉換爲任何Objective-C對象類型而無需強制轉換。下面的兩行是等效的:

id someId = ...; 
NSString *someString = someId; // #1 
NSString *someString = (NSString *)someId; // #2 

這類似於如何在C,void*類型的指針可以隱式轉換的指針的任何其它類型不進行強制轉換(即也目標C的真,但在Objective-C中不鼓勵使用void*指針;即在C++中爲而不是爲真)。

就類型安全而言,兩者都相當不安全。如果該對象的運行時類型實際上是您要將其轉換爲的類型(不管該類型是明確的還是隱式的)或其子類,那麼一切都將按預期工作。如果運行時類型是而不是您期待的內容,那麼最有可能的是NSException將與普通的object does not response to selector錯誤一起拋出,這是由於調用了該類型不存在的函數。由於訪問不存在或具有意想不到的值的ivar(因爲該對象實際上不是該類型),您可能會因分段錯誤而崩潰。

如果你不確定該對象的運行時類型的,應檢查其運行時類型與-class-isKindOfClass: methods, and then only take action if it's a particular type. Prefer using -isKindOfClass:`,因爲這仍與子類的工作,而不是爲準確平等類與特定的比較類。例如:

id someId = ...; 
if ([someId isKindOfClass:[NSString class]) 
{ 
    // It's an NSString 
    NSString *someString = someId; 
    // Do stuff with someString... 
} 
+0

非常感謝您的詳細說明。 –