2011-12-18 40 views

回答

6

只有當編譯器無法繼續執行時纔會發生錯誤,因爲出現嚴重錯誤。

在Objective-C中調用方法時,方法查找是在運行時完成的,而不是在編譯期間完成的,而C++則是這樣做的。在Objective-C中,「消息」只是發送給對象,如obj.executeCommand("Hey, can you execute function <name> for me?")。在C++中,對象將被直接調用,如obj.<name>()。在Objective-C的情況下,調用executeCommand()方法,該方法存在。在C++中,函數被調用,但不存在。這些是在編譯器級別鏈接的方法,這意味着它們都成爲內存地址而不是名稱。 executeCommand變爲0x12345678,但仍使用相同的消息("execute function <name>")。

這可能很混亂,但它與方法在不同語言中的實現方式有關。

0

我不知道真正的答案,但這裏是一個用例,它會違背它。

如果你在一個類中實現了所有的協議方法會怎樣?

主界面聲明採用協議,但協議方法實現在一個類別中。 這是有效的代碼,但會顯示編譯錯誤,如果編譯器是嚴格的!

2

如果您對此感到強烈,爲什麼不打開-Werror

0

Objective-C是一種動態語言。什麼是實現的概念與靜態語言不同。
大部分情況下,我們大多數人都是在@implementation ... @end塊中執行代碼。
但是如果找不到方法呢?然後一個對象有機會動態地處理它。

假設你有一個音效播放器的界面:

@protocol FX 
- (void)playBeep; 
- (void)playSiren; 
- (void)playHonk; 
@end 

實現可能有文件Beep.mp3,Siren.mp3,鳴喇叭。MP3播放,但是,不是每個實施的方法,它可以覆蓋-forwardInvocation:並解析選擇器字符串,這樣的僞東西:

NSString *selName = NSStringFromSelector([invocation selector]); 
if ([selName startsWith:@"play"]) { 
    NSString filename = fileNameFromSelector(selName); 
    [self playSoundFileNamed:filename]; 
} 

這似乎做作,但一旦你開始使用這種語言的動態特徵,你會開始在越來越多的地方找到合理的位置。從意義上說,我的意思是,從長遠來看是否有幫助?

在上面的例子中,只需在接口中添加一個-sound *方法名稱,然後放入一個適當命名的聲音文件即可。它只是工作。

個人實驗的另一個例子:如何以更自然的方式處理核心數據實體。我想這樣做: NSArray * people = [Person findAllWithNameLike:@「B%」]; ,而不是用謂詞,獲取請求等。
但我不想在代碼中定義每個方法的排列。

如果我想構建一個XML生成器,那麼該怎麼辦?我會看看一個動態的方法。它爲Groovy Builders提供了很好的服務(以Groovy/Grails爲例)。最後一個例子:我有一個特徵系統,我可以用方法組的形式定義行爲,讓我的對象同化這種行爲。所以,雖然編譯器沒有看到我的對象符合的接口的實現,但是使用Objective-C運行時將實現從特徵類注入到它中。我爲什麼要這樣做?我發現許多代表方法都是鍋爐板,但同時,每種情況的單個基類都不夠靈活。而不是從代碼示例中剪切和粘貼,我的「樣本」編譯並運行:),並且所有使用該特徵的項目都會反映出任何更改。

要真正理解爲什麼所有這些都適合您,值得玩耍一下Smalltalk環境(搜索Pharo或Squeak)。這就是Objective-C的起源。

最後,停止這些警告:

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wprotocol" 

@implementation ... @end 

#pragma clang diagnostic pop 
0

因爲有些時候也有假的「要求」在一個設計不當的協議方法次。 他們應該是可選的,但有人堅稱他們是「必需的」。 因此,使這個運行時問題而不是編譯錯誤是非常明智的。

相關問題