Skip to end of metadata
Go to start of metadata


もしあなたがGroovyをしばらく使っているなら、あなたは確実にカテゴリーの概念に慣れ親しんでいるでしょう。これは既存の型に新しいメソッドを追加して拡張するためのメカニズム(JDKのfinalクラスであったり、サードパーティ製のライブラリであってたとしても)です。この技術はドメイン固有言語(Domain-Specific Language: DSL)を書く技術でもあります。以下の例を考えてみましょう。


ここでは話を単純化するための、架空のサードパーティ製のDistanceクラスです。誰がやらかしたのか、classはfinalにされてしまっており、もうどんな方法を使っても誰も拡張することができません。しかし、GroovyのカテゴリーのおかげでDistance型にメソッドを追加して装飾することができます。さて、実際にNumber型にgetMeters()メソッドを追加して数値を装飾してみましょう。ゲッターを数値に追加する場合、Groovyのよい構文を使ってそれを参照することができます。なので、300.getMeters()と書く代わりに、300.metersと書くことができます。


このカテゴリーシステムとノーテーションのマイナス面はインスタンスメソッドを他の型に追加することです。staticメソッドを作らなければなりません。そしてさらに、利用する型を表すインスタンスを第一引数として取り組む必要があります。他の引数は普通にメソッドがパラメータとして利用するものです。なのでDistanceに普通のメソッドとして追加するための宣言と比べると直感性に欠けます。それを拡張するためにソースコードにアクセスしたはずです。そこで@Categoryアノテーションの登場です。これはインスタンスメソッドを持つクラスをGroovyカテゴリに変換します。


メソッドをstaticとして宣言する必要はありません、そして、これが実際にNumberに適用されるカテゴリーです。これは我々が作るべきカテゴリーの本物のインスタンスではありません。そしてカテゴリーを使うために、続けて use(Category) {} 構造を使うことができます。この種類のカテゴリーは一度に型が一つだけしか受け付けません。以前からのカテゴリーと異なるのは、多くの型を適用できることです。


さて、 @Category 拡張を @Mixin 変換と組み合わせてみましょう。多重継承のアプローチに似ている振る舞いをクラスの変数に混ぜ込むことができます。


様々なインタフェースを継承する代わりにあなたのクラスにカテゴリをミックスインすることによって振る舞いを挿入することができます。


これを作成する重要な点は、デリゲートが宣言されたクラスへ inject できる@Delegateのインタフェースとは異なっていることです。@Mixinは実行時のミックスインのみ行います(この記事のさらに以降でメタプログラミング拡張をお見せするように)。

  • No labels