2009-06-13 79 views

回答

80

首先,一點點historical perspective on the topic,從Java的創造者之一。接下來,維基百科有一個溫和的幫助section on Objective-C protocols。特別是,Objective-C支持正式協議(它們明確聲明爲@protocol關鍵字,相當於Java接口)和非正式協議(僅由一個類實現的一個或多個方法,可以是通過反射發現)。

如果你採用正式協議(Objective-C中的術語爲「實現一個接口」)編譯器將發出對未實現的方法警告,正如你所期望的在Java中。 與Java(如skaffman提到的),如果一個Objective-C類實現包含在正式協議中的方法,據說這是「順應」該協議,即使它的接口不明確採納。你可以像這樣的代碼測試協議一致性(使用-conformsToProtocol:):

if ([myObject conformsToProtocol:@protocol(MyProtocol)]) { 
    ... 
} 

注:蘋果公司的documentation狀態:

「這種方法確定單獨的正式聲明在頭文件的基礎上,符合,如上圖所示,它不檢查協議中聲明的方法是否實際執行 - 這是程序員的責任。「

作爲目的-C 2.0的(在OS X 10.5「豹」和IOS)正式的協議現在可以定義可選方法,並且只要它實現所有需要的方法的類符合一協議。您可以使用@required(默認)和@optional關鍵字來切換是否遵循的方法聲明必須執行可能以符合協議。 (請參閱討論optional protocol methods的蘋果Objective-C 2.0 Programming Language指南部分。)

可選協議方法開拓了很大的靈活性,以開發,特別是用於實現代表聽衆。而不是擴展MouseInputAdapter(這可能很煩人,因爲Java也是單一繼承)或實現了許多毫無意義的空方法,您可以採用協議並僅實現您關心的可選方法。有了這個模式,主叫方檢查方法是否(使用-respondsToSelector)像這樣調用前執行:

if ([myObject respondsToSelector:@selector(fillArray:withObject:)]) { 
    [myObject fillArray:anArray withObject:foo]; 
    ... 
} 

如果反射的開銷成爲一個問題,你可以隨時cache the boolean result for reuse,但抵制的衝動,過早優化。 :-)

18

它們幾乎完全相同。不過,有一件事讓我意識到,除非你明確聲明目標C協議也實現NSObject,否則對該協議的引用不能訪問NSObject聲明的方法(不管編譯器警告如何)。用java你可以有一個接口的引用,並仍然調用toString()等。

例如

目標C:

@protocol MyProtocol 
// Protocol definition 
@end 

id <MyProtocol> myProtocol; 

[myProtocol retain] // Compiler warning 

爪哇:

public interface MyInterface { 
// interface definition 
} 

MyInterface myInterface; 

myInterface.toString(); // Works fine. 

目標C(固定):

@protocol MyProtocol <NSObject> 
// Protocol definition 
@end 

id <MyProtocol> myProtocol; 

[myProtocol retain] // No Warning 
+25

這是因爲id和NSObject *不一樣*。在Java中,根對象是Object。在Objective-C中,NSObject是一個根對象,但不是*根對象。如果你想訪問所有的NSObject方法(類方法和協議),請明確聲明:NSObject myProtocol;而不是:id ...當你使用id時,你會說:我不關心這個對象,*只是*協議,在你的情況下,它不是真的。 – 2009-06-13 12:14:02

+0

@JasonCoco cool:D – hqt 2014-07-15 16:48:10