@Delegate アノテーションをチョット使ってみて思ったことをメモ。
普通の使い方
まずは普通の使い方。 Wrapper1 クラスに Inner1 型のプロパティ inner を定義して、それに処理を委譲したいときは以下のように書きます:
class Wrapper1{ @Delegate Inner1 inner Wrapper1(){ this.inner = new Inner1(prop1:'1st Property') } } class Inner1{ def prop1 }
このとき、Wrapper1 オブジェクトに prop1 プロパティがあるようにコードを書けます:
def var1 = new Wrapper1() assert var1.prop1 == '1st Property'
まぁ、なんて便利なんでしょう。
Apparent or Actual ?
さて、次のような Inner1 クラスのサブクラス Inner2 があったとしましょう:
class Inner2 extends Inner1{ def prop2 }
そして Wrapper2 クラスが以下のように定義されているとします:
class Wrapper2{ @Delegate Inner1 inner Wrapper2(){ this.inner = new Inner2(prop1:'1st Property', prop2:'2nd Property') } }
このとき、先ほどと同じように
def var2 = new Wrapper2() assert var2.prop1 == '1st Property' assert var2.prop2 == '2nd Property'
としたらどうなるでしょう? 一見なんの問題もないように見えるかも知れませんが(拙者だけ?)、実際には prop2 プロパティにアクセスしようとした時点(3行目)で groovy.lang.MissingPropertyException が投げられます。
この原因は、Wrapper2 のプロパティとして、inner を Inner1 型で宣言しているためです。 この振る舞いから察するに、@Delegate はプロパティの本当の型 (Actual type) ではなく、表面的な型 (Apparent type) に依存するようです。
では、
class Wrapper2{ @Delegate Inner2 inner Wrapper2(){ this.inner = new Inner2(prop1:'1st Property', prop2:'2nd Property') } }
とすれば、問題なく
def var2 = new Wrapper2() assert var2.prop1 == '1st Property' assert var2.prop2 == '2nd Property'
が実行できるかというと、今度は prop1 プロパティへアクセスする際(2行目)に groovy.lang.MissingPropertyException が投げられます。 正直、これはバグではないかと。 もしそうなら、先ほどの「表面的な型に依存する」ってのもそうかもしれませんが。
さらに Generics も混ぜてみた
もういいよ・・・って思われるかも知れないけど、更に Generics も混ぜて試してみた。
まず、次のようなクラスを作ってみる:
class GenericWrapper<I extends Inner1>{ @Delegate I inner GenericWrapper(I inner){ this.inner = inner } }
で、試すのは次のようなコード:
def i1 = new Inner1(prop1:'1st Property') def i2 = new Inner2(prop1:'1st Property', prop2:'2nd Property') def var3 = new GenericWrapper<Inner1>(i1) assert var3.prop1 == '1st Property' def var4 = new GenericWrapper<Inner1>(i2) assert var4.prop1 == '1st Property' assert var4.prop2 == '2nd Property' def var5 = new GenericWrapper<Inner2>(i2) assert var5.prop1 == '1st Property' assert var5.prop2 == '2nd Property'
さて、どのプロパティ・アクセスが失敗するでしょう?(1つとは限らない)
まず、上記のサブクラスの例からすると3つ目のアサーション中の「var4.prop2」が失敗する(例外が投げられる)と予想されるますが、実際失敗します。 んで、もうひとつ、5つめのアサーション中の「var5.prop2」も失敗します(例外が投げられる)。
まぁ、この辺りになってくると、仕様とかバグとか関係なく、使わない方が無難そうですけど。
- 作者: Dierk Konig,Andrew Glover,Paul King,Guillaume Laforge,Jon Skeet,杉浦孝,櫻井正樹,須江信洋,関谷和愛,佐野徹郎,寺沢尚史
- 出版社/メーカー: 毎日コミュニケーションズ
- 発売日: 2008/09/27
- メディア: 単行本(ソフトカバー)
- 購入: 5人 クリック: 146回
- この商品を含むブログ (121件) を見る
Programming Groovy: Dynamic Productivity for the Java Developer (The Pragmatic Programmers)
- 作者: Venkat Subramaniam
- 出版社/メーカー: Pragmatic Bookshelf
- 発売日: 2008/04
- メディア: ペーパーバック
- クリック: 8回
- この商品を含むブログ (8件) を見る