クラス拡張とクラスカテゴリ


82

クラス拡張@interface Class () ははるかに強力であり、クラスに変数を挿入できます。カテゴリ@interface Class (Category)はできません。

他にどのような違いがあり、クラス拡張よりもカテゴリを使用する必要があるのはいつですか?


カテゴリは実際のコードです。これらは、クラスに機能を追加する方法です。拡張機能は(非常に一般的な用語で)他のプログラマーにプライバシーなどに関する特定のアイデアを知らせるための単なる構文糖衣です。拡張機能にはコードが含まれておらず、コードではありません。
Fattie

彼らはスウィフトに使用されているよう拡張のために、この質問を参照してください。stackoverflow.com/questions/24142829/...
Suragch

回答:


91

主な違いは、拡張機能を使用すると、コンパイラはメイン内にメソッドを実装することを期待するの@implementationに対し、カテゴリを使用すると、別の@implementationブロックがあることです。したがって、メイン.mファイルの先頭にある拡張子のみを使用する必要があります(ちなみに、ivarを気にする必要がある唯一の場所)-それはまさにそれ、つまり拡張子であることを意味します。


41
拡張機能は、.mファイルで宣言するプライベートメソッドに最適です。私はいつもこれに使っています。カテゴリは、メソッドをさまざまなセクション(カテゴリ:))にグループ化する場合、または作成していない既存のクラスにコードを追加する場合に役立ちます。
jtbandes 2011

1
プロパティを使用して、クラス拡張機能であるストレージを追加することもできます。
Paul.s 2011

23
クラス拡張は、プロパティをパブリックreadonlyおよびプライベートにできるように特別に設計されていますreadwrite。カテゴリではそれを行うことはできません(意識的なデザインの選択)。
bbum 2012

Googleが拡張機能ではなくカテゴリを使用してプライベートメソッドを実装しているのはなぜですか?例:code.google.com/p/gdata-objectivec-client/source/browse/trunk/…–
ライアン

拡張機能では、すべてのメソッドを@implementationブロックに実装する必要があります。また、変数の拡張機能も提供します。しかし、基本的にはプライベート変数を使用する代わりにいくつかのプライベートメソッドを配置しようとしているため、その場合は拡張ではなくカテゴリを優先します
Ankit Thakur 2012

29

クラス拡張はカテゴリとある程度類似していますが、コンパイル時にソースコードがあるクラスにのみ追加できます(クラスはクラス拡張と同時にコンパイルされます)。クラス拡張によって宣言されたメソッドは、元のクラスの@implementationブロックに実装されているため、たとえば、CocoaやNSStringなどのCocoaTouchクラスなどのフレームワーククラスでクラス拡張を宣言することはできません。

クラス拡張を宣言する構文は、カテゴリの構文に似ており、次のようになります。

@interface ClassName ()
@end

括弧内に名前が指定されていないため、クラス拡張は匿名カテゴリと呼ばれることがよくあります。

通常のカテゴリとは異なり、クラス拡張機能は独自のプロパティとインスタンス変数をクラスに追加できます。次のように、クラス拡張でプロパティを宣言する場合:

@interface XYZAnimal () {
    id _someCustomInstanceVariable;
}
...
@end

私見ですが、クラス拡張はクラスへのプライベートインターフェイスと考えるのが最善です。(.hファイル内の)プライマリインターフェイスは、他のクラスとのクラスの動作コントラクトを定義するパブリックインターフェイスとして機能します。

クラス拡張を使用して個人情報を非表示にする

クラス拡張は、クラス自体の実装内で使用するための追加のプライベートメソッドまたはプロパティを使用してパブリックインターフェイスを拡張するためによく使用されます。たとえば、プロパティをインターフェイスで読み取り専用として定義するのが一般的ですが、クラスの内部メソッドがプロパティ値を直接変更できるようにするために、実装の上で宣言されたクラス拡張で読み取り/書き込みとして定義します。

例として、XYZPersonクラスは、米国の社会保障番号などの情報を追跡するように設計された、uniqueIdentifierというプロパティを追加する場合があります。

通常、実世界の個人に一意の識別子を割り当てるには大量の事務処理が必要になるため、XYZPersonクラスインターフェイスはこのプロパティを読み取り専用として宣言し、次のように識別子の割り当てを要求するメソッドを提供する場合があります。

@interface XYZPerson : NSObject
    ...
    @property (readonly) NSString *uniqueIdentifier;
    - (void)assignUniqueIdentifier;
@end

XYZPersonクラスがプロパティを内部で変更できるようにするには、クラスの実装ファイルの先頭で定義されているクラス拡張子でプロパティを再宣言するのが理にかなっています。

@property (readwrite) NSString *uniqueIdentifier;

注:readwrite属性はデフォルトであるため、オプションです。わかりやすくするために、プロパティを再宣言するときに使用することをお勧めします。


7

カテゴリは、既存のクラスに新しいメソッドを追加できるObjective-C言語機能です。拡張機能は、メインの実装ブロックに実装する必要のあるメソッドを定義できるカテゴリの特殊なケースです。

プライベート宣言は、メソッドを呼び出す前にメソッドを宣言する必要がないため、主に一部のプロパティであるクラス拡張に含めることができます。


「それはメインの実装ブロックで宣言する必要があります。」->メインの実装ブロックで「実装」する必要があります
Fawkes 2016年

おかげで、私はそれを変更しました。
Julie Yu

0

c#に類似したios拡張、java抽象クラスまたは
c#クラス拡張に類似したインターフェース iosカテゴリー


Javaは拡張メソッドをサポートしていません
someUser 2016年

ごめんなさい !コピー&ペーストのタイプミス。c#クラス拡張に類似したiosカテゴリ。
add080bbA 2016年

について例を追加できますか?
PedroTrujillo19年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.