この記事、どれだけの人に需要があるのですかね?
概要
カテゴリとは、既存のクラスに対してメソッドを追加する機能。既存のクラスを再コンパイルする必要がなく、クラスの挙動を変更することができる。
Groovyのカテゴリは、Objective-C由来です。Objective-Cの由来は知りません。
簡単な比較
はっきりいって概要以外の点は、全く違うといっていい。実装上の問題もあると思います。Objective-C側から見たらGroovyのカテゴリはより洗練されて見えるどろうけど、逆側から見たら怖くて使えないかもしれません。
それぞれの書き方
// Objective-C @interface NSObject (BetterHash) - (unsigned)hash; @end @implementation NSObject (BetterHash) // 子孫クラスのうち、独自のオーバーライドのない-hashは全てこの実装に置き換わる - (unsigned)hash { return better_hash_function(self); } @end NSObject *obj = [NSObject new]; [obj hash];
// Groovy @Category(Number) class NumberCategory { int hoge() { better_hash_function(this) } } use(NumberCategory) { 100.hoge() }
詳しい比較
実装方法
Groovyは別のクラスを作りそのクラスのメソッドにオブジェクトを渡すことによって解決しているようです。これは、ひとつのアプリではあるクラスにおいてあるメソッドは複数の動きをする可能性があります。
Objective-Cでは、コンパイル時にメソッドを追加、上書きしているような動きをします。これは、ひとつのアプリではあるクラスにおいてのあるメソッドは一つの動きをすることになります。
局所性の有無
Groovyには局所性が存在しますが、Objective-Cにはありません。
Groovyでは、useによってカテゴリを使用する範囲を指定することができます。これによって使われる範囲を限定し混乱を避ける事ができるでしょう。一方で、頻繁に使いたい場合は記述量が増えることになる。この場合は別のメタプログラミングで解決することになるでしょう。
Objective-Cには、局所性はありません。コンパイル時にアプリ全体にカテゴリが適用されます。使おうと思えば、importしなくても使えてしまうので、カテゴリに馴染みのない人にとっては、非常にわかりにくいかもしれません。大抵の場合は記述量が減るので、Objective-Cの人は好んで使っているようです。局所性のあるメタプログラミングの方法は私の知る限りでは存在しません。
複数のカテゴリ
複数のカテゴリで同じメソッドを実装した場合、どのような挙動になるか?
Groovyでは、複数のカテゴリが同じメソットを実装していたとしても、useによってカテゴリを使い分けつことができます。さらに、複数のカテゴリを同時に使った場合は最後にuseをしたものが優先されます。
Objective-Cでは、複数のカテゴリが同じメソットを実装していた場合、どれか一つが実装され使い分けることができません。どれが実装されるかはリンクの順番に依存すると思われます。実質どのカテゴリが使えるかがわかりません。複数カテゴリを使用する場合は注意が必要です。
まとめ
Groovyのカテゴリは素敵だがカテゴリと名乗ってるのは、なにか違う気がします