Objective-C には、クラスを複数のファイルに分割して宣言、及び定義するための機能を提供しています。 これをカテゴリと呼び、カテゴリを利用することでクラスのメソッド宣言を分割することが出来ます。 例えば、複数の開発者が共同で、同時平行で同一クラスの実装を記述するような場合、それぞれの開発者にはクラスのうち、開発者が担当するメソッドをカテゴリに分割します。
カテゴリを宣言するには、必ずメインとなるクラスのインタフェース宣言が必要です。 クラスのカテゴリを宣言、及び定義する場合は、次のような構文を指定します。
@interfae クラス名 (カテゴリ名) { ...
@implementation クラス名 (カテゴリ名) { ...
ここで指定するカテゴリ名は、C 言語の識別子の命名規則に従います。 カテゴリ化するクラスは、必ず、すでにメインとなる本体が宣言されていなければなりません。
カテゴリは通常のクラスの宣言や定義に似ていますが、インスタンス変数を宣言することが出来ないので注意してください。 カテゴリが宣言できるのは、インスタンスメソッドとクラスメソッドだけです。
#import <stdio.h>
#import <objc/Object.h>
@interface Test : Object
- (void)WriteA;
@end
@interface Test (Fate)
- (void)WriteB;
@end
@implementation Test
- (void)WriteA {
printf("I am the bone of my sword.\n");
}
@end
@implementation Test (Fate)
- (void)WriteB {
printf("体は剣で出来ている\n");
}
@end
int main() {
id obj = [Test new];
[obj WriteA];
[obj WriteB];
[obj free];
return 0;
}
このプログラムは、Test クラスをメインと Fate という名前を持つカテゴリに分割しています。 実行結果は、想像のとおりです。 Test クラスの、分割されているすべてのカテゴリは、最終的に同一のクラスとして統合されます。 もちろん、カテゴリは他のファイルで宣言してもかまいません。 その場合、カテゴリを宣言するファイルはメインとなるクラスを宣言するヘッダファイルをインクルードしている必要があります。
カテゴリは、既存の完成しているクラスに機能を追加するという目的で使うことも出来ます。 ただし、インスタンス変数を追加することは出来ないので、既存のクラスの役割の範囲での拡張ということになります。
#import <stdio.h>
#import <objc/Object.h>
@interface Object (Write)
- (void)Write;
@end
@implementation Object (Write)
- (void)Write {
printf("I am the bone of my sword.\n");
}
@end
int main() {
id obj = [Object new];
[obj Write];
[obj free];
return 0;
}
このプログラムは、ルートクラスである Object クラスに新しいカテゴリを追加してます。 因みに、カテゴリのメソッドが既存クラスのメソッドと衝突した場合、カテゴリのメソッドが優先され、既存のメソッドは隠蔽されてしまいます。 継承によるオーバーライドとは異なるため、隠蔽されたメソッドを呼び出す手段がなくなってしまうので注意してください。