クラス拡張@interface Class ()
は、はるかに強力で、クラスに変数を注入できます。カテゴリ@interface Class (Category)
はできません。
他にどのような違いがありますか?クラス拡張よりもいつカテゴリを使用する必要がありますか?
主な違いは、拡張機能を使用すると、コンパイラはメインの@implementation
、カテゴリには個別の@implementation
ブロック。したがって、メインの.m
ファイル(偶然ivarsを気にする必要がある唯一の場所)-それはまさに、拡張子であることを意味します。
クラス拡張はカテゴリとある程度類似していますが、コンパイル時にソースコードを持っているクラスにのみ追加できます(クラスはクラス拡張と同時にコンパイルされます)。クラス拡張機能によって宣言されたメソッドは、元のクラスの@implementationブロックに実装されているため、たとえば、CocoaやNSStringなどのCocoa Touchクラスなどのフレームワーククラスでクラス拡張機能を宣言することはできません。
クラス拡張を宣言する構文は、カテゴリの構文に似ており、次のようになります。
@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属性はデフォルトであるため、オプションです。明確にするために、プロパティを再宣言するときに使用することができます。
カテゴリは、既存のクラスに新しいメソッドを追加できるObjective-C言語の機能です。拡張機能は、メイン実装ブロックで実装する必要があるメソッドを定義できるカテゴリの特殊なケースです。
プライベート宣言は、クラス拡張で行うことができます。これは、主にいくつかのプロパティです。メソッドを呼び出す前に宣言する必要がないためです。