2009-06-13 19 views

答えて

80

最初に、Javaの作成者の一人から少しhistorical perspective on the topicが届きました。次に、Wikipediaは適度に役立つsection on Objective-C protocolsを持っています。特に、Objective-Cはフォーマルプロトコル(Javaインターフェイスに相当する@protocolキーワードで明示的に宣言されています)とインフォーマルプロトコルをサポートしています(クラスによって実装された1つ以上のメソッドだけです。反射によって発見された)。

正式なプロトコル(「インターフェイスを実装する」のObjective-Cの用語)を採用すると、コンパイラはJavaで期待するように実装されていないメソッドについて警告を出します。 Objective-Cクラスが正式なプロトコルに含まれるメソッドを実装する場合、Javaとは異なり(skaffman)、そのインタフェースが明示的にそれを採用していなくてもそのプロトコルに準拠していると言われています。あなたはこのように(-conformsToProtocol:を使用して)コードでプロトコルの適合性をテストすることができ

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

注:Appleのdocumentation状態:

「このメソッドは、単にヘッダファイルでの正式な宣言に基づいて適合性を判断しプロトコルで宣言されたメソッドが実際に実装されているかどうかを確認することはありません。それがプログラマーの責任です」と述べています。 Objective-Cの2.0(OS X 10.5「ヒョウ」とIOS)のよう

、正式なプロトコルは、現在任意の方法を定義することができ、クラスは、それが必要なすべてのメソッドを実装するようにプロトコルに準拠。 @required(デフォルト)および@optionalキーワードを使用して、に続くメソッド宣言が、またはをプロトコルに準拠して実装する必要があるかどうかをトグルすることができます。 (AppleのObjective-C 2.0 Programming Languageガイドのoptional protocol methodsについて説明するセクションを参照してください。)

オプションのプロトコルメソッドは、特に代表者リスナーを実現するために、開発者に多くの柔軟性を開きます。 MouseInputAdapter(Javaは単一継承であるため厄介なことがある)のようなものを拡張するか、無意味で空のメソッドをたくさん実装する代わりに、プロトコルを採用して気になるオプションのメソッドだけを実装することができます。このパターンでは、呼び出し側は方法は(-respondsToSelectorを使用して)ので、同じようにそれを呼び出す前に実装されているかどうかをチェックします。反射のオーバーヘッドが問題になる場合

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

、あなたは途中で最適化するために衝動に抵抗するcache the boolean result for reuse常にすることができますが、 。 :-)

+4

"正式なプロトコル(Objective-Cという用語を"インタフェースを実装する "とする)を採用すると、コンパイラはJavaの場合と同様に、実装されていないメソッドに対して警告を発します。この場合、Javaは警告ではなくエラーを出力します。 –

+3

"Objective-Cクラスが正式なプロトコルに含まれているメソッドを実装している場合、インタフェースが明示的にそれを採用していなくても、そのプロトコルに"適合 "していると言われます。-conformsToProtocol :)このように "これは嘘です。 '-conformsToProtocol:'はクラスが明示的にプロトコルを採用している場合のみYESを返します。あなたはそれを試したことがありますか? – user102008

+2

正しいですが、 '-conformsToProtocol:'実際にクラス(または祖先)がプロトコルを採用することを正式に宣言することを要求しています。どのように私は間違って、訂正のおかげで得たかわからない! –

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を使用すると、私はオブジェクトについて気にしません。あなたの場合には当てはまりません。 –

+0

@JasonCoco cool:D – hqt

関連する問題