プロトコルとカテゴリー
-
21-08-2019 - |
質問
誰かが間の違いを説明できますか プロトコル そして カテゴリー Objective-Cでは?いつ一方を他方よりも使用しますか?
解決
プロトコルは Java のインターフェイスと同じものです。それは本質的に次のような契約です、 「このプロトコルを実装するクラスは、これらのメソッドも実装します。」
一方、カテゴリはメソッドをクラスにバインドするだけです。たとえば、 ココア, のカテゴリを作成できます。 NSObject
これにより、メソッドを追加できるようになります NSObject
クラス (そしてもちろんすべてのサブクラス)、 実際にアクセスできないにもかかわらず NSObject
.
要約する: プロトコルは、クラスが実装するメソッドを指定します。カテゴリは既存のクラスにメソッドを追加します。
したがって、それぞれの適切な使用法は明らかです。 プロトコルを使用してクラスが実装する必要があるメソッドのセットを宣言し、カテゴリを使用して既存のクラスにメソッドを追加します。
他のヒント
プロトコルには「ここに私が望むいくつかのメソッドがあります」と書かれています。 あなた カテゴリには、「これらの追加メソッドを使用してこのクラスの機能を拡張しています。」と記載されています。
さて、あなたの混乱は Apple が「非公式プロトコル」という言葉を使っていることに起因しているのではないかと思います。重要な(そして最も混乱を招く)ポイントは次のとおりです。非公式プロトコルは実際にはプロトコルではありません。これは実際には NSObject のカテゴリです。Cocoa は、非公式プロトコルを広く使用して、デリゲートにインターフェイスを提供します。以来、 @protocol
Objective-C 2.0 まで、構文ではオプションのメソッドが許可されていなかったため、Apple は何もしない (またはダミー値を返す) オプションのメソッドを実装し、例外をスローするメソッドを要求しました。コンパイラを通じてこれを強制する方法はありませんでした。
さて、Objective-C 2.0 では、 @protocol
構文は、 @optional
キーワードを使用して、プロトコル内の一部のメソッドをオプションとしてマークします。したがって、クラスは、次のようにマークされたすべてのメソッドを実装している限り、プロトコルに準拠します。 @required
. 。コンパイラは、クラスが必要なメソッドをすべて実装しているかどうかも判断できるため、時間を大幅に節約できます。iPhone SDK は Objective-C 2.0 のみを使用します @protocol
構文に依存しており、新しい開発でこれを使用しない正当な理由が思いつきません (Mac OS X の以前のバージョンで実行する必要がある Mac OS X Cocoa アプリを除く)。
カテゴリ:
カテゴリは、クラス自体を変更せずに、既存のクラスのすべてのインスタンスに新しいメソッドを追加する方法です。
カテゴリは、既存のクラスから派生したり、元のクラスを書き直したりせずに、既存のクラスに機能を追加する場合に使用します。
を使用しているとしましょう NSView
Cocoa のオブジェクトを作成すると、すべてのインスタンスが NSView
何らかのアクションを実行することができました。当然、書き換えることはできません NSView
クラスから派生したとしても、すべてのクラスがそうであるわけではありません。 NSView
プログラム内のオブジェクトは派生型になります。解決策は、カテゴリを作成することです NSView
, これをプログラムで使用します。あなたが〜をするなら #import
カテゴリ宣言を含むヘッダー ファイルは、次のように表示されます。 毎 NSView
オブジェクトは、カテゴリ ソース ファイルで定義したメソッドに応答します。
プロトコル:
プロトコルは、任意のクラスが実装を選択できるメソッドのコレクションです。
特定のクラスが特定のメソッドのセットに応答することを保証したい場合は、プロトコルを使用します。クラスがプロトコルを採用すると、プロトコル ヘッダーで宣言されたすべてのメソッドを実装することが約束されます。つまり、そのクラスを使用する他のクラスは、そのクラスについて何も知らなくても、それらのメソッドが確実に実装されることを確認できます。
これは、すべてが共通の「コントローラー」クラスと通信する必要がある類似したクラスのファミリーを作成する場合に役立ちます。コントローラー クラスと制御対象クラス間の通信はすべて、単一のプロトコルにパッケージ化できます。
サイドノート:object-c 言語は多重継承をサポートしていません (クラスは 1 つのスーパークラスからのみ派生できます)。ただし、クラスは複数の異なるプロトコルに準拠できるため、同じ機能の多くはプロトコルによって提供できます。
私の理解では、プロトコルは Java のインターフェイスに少し似ています。プロトコルはメソッドを宣言しますが、実装は各クラスに任されています。カテゴリはRubyのミックスインのようなもののようです。カテゴリを使用すると、既存のクラスにメソッドを追加できます。組み込みクラスも。
プロトコルを使用すると、特定のクラスやカテゴリに限定されないメソッドのリストを宣言できます。プロトコルで宣言されたメソッドは、任意のクラス/カテゴリに採用できます。プロトコルを採用するクラスまたはカテゴリは、プロトコルで宣言されている必要なメソッドをすべて実装する必要があります。
カテゴリを使用すると、既存のクラスにメソッドを追加できますが、インスタンス変数を追加することはできません。カテゴリが追加するメソッドはクラス型の一部になります。
プロトコルは、指定されたメソッドを実装するための規約です。プロトコルに準拠するオブジェクトはすべて、それらのメソッドの実装を提供することに同意します。プロトコルの有効な使用法は、デリゲートのコールバック メソッドのセットを定義することです (デリゲートはすべてのメソッドに応答する必要があります)。
カテゴリは、現在のオブジェクトにメソッド (クラス メソッドまたはインスタンス メソッド) を追加することで、そのオブジェクトを拡張する機能を提供します。カテゴリの有効な用途は、NSString クラスを拡張して、受信機を 1337 5P34K に変換する新しい文字列を作成するメソッドを追加するなど、以前には存在しなかった機能を追加することです。
NSString *test = @"Leet speak";
NSString *leet = [test stringByConvertingToLeet];
S.G.Kochan の「Programming in Objective-C」からの定義:
カテゴリ:
カテゴリを使用すると、クラスの定義を関連メソッドのグループまたはカテゴリにモジュール化する簡単な方法が提供されます。また、クラスの元のソース コードにアクセスしたり、サブクラスを作成したりせずに、既存のクラス定義を拡張する簡単な方法も提供します。
プロトコル:
プロトコルは、クラス間で共有されるメソッドのリストです。プロトコルにリストされているメソッドには、対応する実装がありません。これらは他の誰か (あなたのような!) によって実装されることを意図しています。プロトコルは、指定された名前に何らかの形で関連するメソッドのセットを定義する方法を提供します。通常、メソッドは文書化されているため、メソッドの実行方法がわかり、必要に応じてメソッドを独自のクラス定義に実装できます。プロトコルには一連のメソッドがリストされており、その一部はオプションで実装でき、その他は実装する必要があります。特定のプロトコルに必要なメソッドをすべて実装することを決定した場合、そのプロトコルに準拠または採用したと言われます。すべてのメソッドがオプションであるプロトコル、またはすべてが必須であるプロトコルを定義できます。