回答:
まず、Javaの作成者の1人による、トピックに関する少し歴史的な視点。次に、ウィキペディアには、Objective-Cプロトコルに関する適度に役立つセクションがあります。特に、Objective-Cは、正式なプロトコル(@protocol
キーワードで明示的に宣言される、Javaインターフェースに相当)と非公式のプロトコル(リフレクションを介して検出できるクラスによって実装される1つ以上のメソッドのみ)の両方をサポートすることを理解してください。
正式なプロトコル(「インターフェースの実装」を表すObjective-Cの用語)を採用した場合、Javaで期待するように、コンパイラーは実装されていないメソッドに対して警告を発します。 Javaとは異なり(スカッフマンが述べたように)、Objective-Cクラスが正式なプロトコルに含まれるメソッドを実装する場合、そのインターフェースが明示的に採用していなくても、そのプロトコルに「準拠」していると言います。次のように、(- conformsToProtocol:を使用して)コードでプロトコルの適合性をテストできます。
if ([myObject conformsToProtocol:@protocol(MyProtocol)]) {
...
}
注:Appleのドキュメントには次のように記載されています。
「このメソッドは、上に示したように、ヘッダーファイルの正式な宣言のみに基づいて適合性を判断します。プロトコルで宣言されたメソッドが実際に実装されているかどうかを確認するのではなく、プログラマの責任です。」
Objective-C 2.0(OS X 10.5 "Leopard"およびiOS)では、正式なプロトコルでオプションのメソッドを定義できるようになり、クラスは必要なすべてのメソッドを実装している限り、プロトコルに準拠しています。あなたは使用することができます@required
(デフォルト)と@optional
フォローをすることをメソッド宣言するかどうかをトグルにキーワードをしなければならないかもプロトコルに準拠するように実装されます。(オプションのプロトコルメソッドについて説明しているAppleのObjective-C 2.0プログラミング言語ガイドのセクションを参照してください。)
オプションのプロトコルメソッドは、特にデリゲートとリスナーの実装において、開発者に多くの柔軟性をもたらします。MouseInputAdapter(Javaも単一継承なので煩わしい場合があります)のようなものを拡張したり、無意味な空のメソッドを多数実装したりする代わりに、プロトコルを採用して、必要なオプションのメソッドのみを実装できます。このパターンを使用すると、呼び出し元は、(- respondsToSelectorを使用して)メソッドを呼び出す前に、次のようにメソッドが実装されているかどうかを確認します。
if ([myObject respondsToSelector:@selector(fillArray:withObject:)]) {
[myObject fillArray:anArray withObject:foo];
...
}
リフレクションのオーバーヘッドが問題になる場合は、ブール値の結果をキャッシュして再利用できますが、時期尚早に最適化したいという衝動には抵抗できます。:-)
-conformsToProtocol:
クラスが明示的にプロトコルを採用している場合にのみYESを返します。あなたもそれを試しましたか?
-conformsToProtocol:
確かに、クラス(または祖先)がプロトコルを採用することを正式に宣言する必要があります。どうしてこれが間違っているのかわからない、修正してくれてありがとう!
それらはほとんど同じです。ただし、私が気付いたのは、目的のCプロトコルがNSObjectも実装していることを明示的に宣言しない限り、そのプロトコルへの参照はNSObjectが宣言したメソッドにアクセスできない(コンパイラの警告なしで)ことです。javaを使用すると、インターフェースへの参照を保持しながら、toString()などを呼び出すことができます。
例えば
目的C:
@protocol MyProtocol
// Protocol definition
@end
id <MyProtocol> myProtocol;
[myProtocol retain] // Compiler warning
Java:
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