Objective-C で既存のクラスを拡張する方法のひとつにカテゴリーを利用する方法があります。
@interface MyClass (CategoryName)
// 追加したいメソッド
@end
カテゴリーですでにあるメソッドと同じ名前のメソッドを追加するとどっちのメソッドが利用されるか分からなくなってしまうという強烈な副作用があるため、利用には注意が必要です。
カテゴリーではインスタンス変数 (メンバー変数) を追加することはできない……と思っていたんですが、私の勘違い?もしかして以前とは動作が変わりました?
@interface MyClass (CategoryName)
{
id _newMember; // <= これは無理
}
- (void)newMethod;
@end
@interface MyClass ()
{
id _newMember; // <= これは OK
}
@end
というコードはできないと思っていたんですが、どうも勘違いだってみたいで普通にできる様子。
やっぱり勘違いでした。カテゴリー名を省略する anonymous categories は「クラス拡張 Class Extensions」とも言って、こっちだとインスタンス変数の宣言ができるようです。
@interface MyClass (CategoryName)
{
id _newMember; // <= これは無理
}
- (void)newMethod1;
- (void)newMethod2;
@end
@interface MyClass ()
{
id _newMember; // <= これは OK
}
@end
@implementation MyClass (CategoryName)
- (void)newMethod1
{
_newMember = ...; // なんか代入
}
- (void)newMethod2
{
NSLog(@"%@",_newMember); // newMethod1 に先にアクセスしていれば、その内容がちゃんと見れる
}
@end
@tomohisaota さんご指摘の通り、この拡張はコンパイラーによって行われるので、ソースコードにアクセスできるような状態でないといけない模様。
UIKit など既存のフレームワークで宣言されたクラスの拡張にはできないようです。試しにやってみたら、リンカでエラーになりました。
Xcode 5.1.1 / iOS SDK 7.1 & OS X SDK 10.9 で確認。
@tomohisaota さん、ありがとうございます。