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