Groovy 1.6 のアノテーション @Mixin と @Delegate
Groovy 1.6 の新機能である @Mixin と @Delegate アノテーションを Groovy 1.6 beta2 で試してみた。
@Mixin と @Delegate が実現する機能は以下の通り。
- @Mixin は実装を取り込む(自分に機能を取り込む)
- @Delegate は委譲処理を実現(自分に機能を取り込まずに他のオブジェクトに処理を委譲)
なお、1.6 beta2 には以下のようなアノテーションも用意されている模様。
- @Singleton
- @Immutable
- @Delegate
- @Lazy
- @Category/@Mixin
- @Newify
@Mixin と @Delegate のサンプル作成
@Mixin と @Delegate を使った以下のようなサンプルを作成。
以下では、SampleFeature クラスを @Mixin アノテーションで取り込んだ MixinSample クラスと @Delegate アノテーションを付与した feature に処理を委譲する DelegateSample クラスに同じメソッドを実行させている。
sample.groovy
class SampleFeature { def name def test(msg) { println "${this} : $name - $msg" } } //Mixin で SampleFeature の実装を取り込み @Mixin(SampleFeature) class MixinSample { void printName() { println name } } //@Delegate アノテーションを付与した feature に処理を委譲 class DelegateSample { @Delegate SampleFeature feature = new SampleFeature() void printName() { println name } } ms = new MixinSample(name: "Mixinテスト") ms.printName() ms.test "call test" //setName が用意されないため以下は不可 //ds = new DelegateSample(name: "Delegateテスト") ds = new DelegateSample() //以下も不可 //ds.name = "Delegateテスト"; ds.feature.name = "Delegateテスト" ds.printName() ds.test "call test"
仕様かどうかは判断つかないが、@Delegate を使った場合には DelegateSample オブジェクトの name に値を設定する事はできない。(そのため、feature の name に値を設定している)
実行結果
>groovy sample.groovy Mixinテスト SampleFeature@1402d5a : Mixinテスト - call test Delegateテスト SampleFeature@18c3679 : Delegateテスト - call test
test メソッドの実行に関しては、どちらも SampleFeature インスタンスのメソッド呼び出しを実行しているようだ。
ここで、DelegateSample で直接 name に値を設定する事ができない原因を調査するため、以下のような処理を追加し、メソッドの一覧を表示してみることにした。
def printMethods = { println "--- ${it} methods ---" it.metaClass.methods.each {m -> println m} } printMethods MixinSample printMethods DelegateSample
結果は以下の通りで、DelegateSample クラスには setName が実装されていない事が判明。さらには @Mixin と @Delegate では実装の仕方が全く異なる事もわかった。
メソッド一覧出力結果(加工済み)
--- class MixinSample methods --- ・・・ org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod@1e2befa[name: getName params: {} returns: class java.lang.Object owner: class MixinSample] org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod@18f51f[name: setName params: {class java.lang.Object} returns: void owner: class MixinSample] org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod@b30913[name: test params: {class java.lang.Object} returns: class java.lang.Object owner: class MixinSample] public void MixinSample.printName() ・・・ --- class DelegateSample methods --- ・・・ public java.lang.Object DelegateSample.getName() public java.lang.Object DelegateSample.test(java.lang.Object) public void DelegateSample.printName() public SampleFeature DelegateSample.getFeature() public void DelegateSample.setFeature(SampleFeature) ・・・