JavaにGroovy混ぜてみた

前回の円周率の件でちょっと気になったので実験してみた。
何の実験かと言えば,「Groovyで改変したJavaのクラスの有効範囲の確認」。GroovyClassLoaderの仕様うんぬんについては,「Groovyイン・アクション(asin:4839927278)」に書いてあったはずなんで,ホンキで取り組むときは観念して購入しよう。:-)


結論から言えば,Groovyで改変した操作はGroovyの中でのみ有効。この結論は予想してたけど,Groovy内で生成したJavaインスタンスに関しても同様だったのが,「へぇ,そうなんだー」的な結果だった。



以下,そのレポート。
こんなコールグラフになるクラス群を作ってだね(J1, J2はJava。G1, G2はGroovy)。G1.first()でBigDecimalの+演算子をオーバロードしてみたよ。

すげー雑でゴメンなソースを文末に晒すんで,とりあえず実行結果だけ張っつけとくよ。

20
20.0
! 30.0
20
! 30.0
! 60.0
20
10


こっからソースコード

--- J1.java ---
import java.math.BigDecimal;

public class J1 {
    public static void main(String[] args) {
        BigDecimal b1 = new BigDecimal(10);
        BigDecimal b2 = new BigDecimal(10);
        System.out.println(b1.add(b2));
        G1.first();
        f();
        G1.second();
        G2.doit();
    }

    public static void f() {
        BigDecimal b1 = new BigDecimal(10);
        BigDecimal b2 = new BigDecimal(10);
        System.out.println(b1.add(b2));
    }
}

--- J2.java ---
import java.math.BigDecimal;

public class J2 {
    public J2() {
        BigDecimal b1 = new BigDecimal(5);
        BigDecimal b2 = new BigDecimal(5);
        System.out.println(b1.add(b2));
    }
}
--- G1.groovy ---
class G1 {
  static void first() {
    println 10.0 + 10.0
    BigDecimal.metaClass.plus = { BigDecimal x ->
      print "! "
      delegate.add(x*2)
    }
    println 10.0 + 10.0
  }

  static void second() {
    println 10.0 + 10.0
  }
}

--- G2.groovy ---
class G2 {
  static void doit() {
    println 20.0 + 20.0
    J1.f()
    new J2()
  }
}


ps.
どうでもいいが,IntelliJCodeExplorerプラグインがGroovyのコードまで追跡してて感動した。
プラグインのデキもさることながら,そんだけPSIが言語問わずに抽象化されたんだなぁとも想像したよ。