Groovyの実験

きっかけはjFD2のGroovyマクロで外部コマンドの実行方法を調べたこと。
当初はJavaでの方法をそのままGroovyに持ってきたのだが、ネットでみたサンプルに驚愕!

"ls -l".execute().in.eachLine{println it}

なんですかこれ?
すぐには理解できなかったが調べてみると、Stringクラスに"execute"メソッドを追加して、ProcessクラスにはInputStreamを取得できるプロパティ"in"を追加しているらしい。やりたい放題だなGroovy。

このコードを見て、気になったことを実験*1
○実験その1
プロパティと書いたが、実際はgetIn()メソッドが追加されているだけらしい。
例えば既存のクラスで

sv=button.getVisible()
button.setVisible(true)

なんて書いていたのを

sv=button.visible
button.visible=true

なんて変えても、同じように動作する。
そこで疑問。
Javaのクラスが

public class Foo{
  public String foo;
  private String bar;
  public Foo(){
    foo="foo";
    bar="bar";
  }
  public String getFoo(){return bar;}
}

だった時にGroovyで

foo=new Foo()
println foo.getFoo()    // ここは"bar"だよね
println foo.foo         // ここは?

とした時どうなるか?
・・結果。
"bar"でした。
"getXXX()"の代わりに"xXX"は安心して使えるということですね。
ちなみに上記のJavaクラスFooからgetFooメソッドを削除すると、ちゃんとpublic変数のfooを参照してくれます。
○実験その2
既存クラスへのメソッドの追加はどうやるか。
Rubyなら簡単だけどJavaじゃできないはず?Groovyでなぜできる?ってのは、このさい追求しないことにする。できるもんはできる。で、やってみた。
まずJavaクラスを用意

public class Foo{
  private String foo;
  public Foo(){
    foo="foo";
  }
}

んで、Groovy

Foo.metaClass.getFoo << {
  return foo;
}
foo=new Foo()
println foo.getFoo()  // foo.fooでも同じ

あっさりJavaのprivateフィールド読めてます。
privateメソッドもラップするメソッドを定義すれば問題なく呼べるでしょう。
それでいいのか?
Java的には問題あるかもしれんけど、まあ便利だからいいんじゃね。

*1:検証環境はGroovy 1.5.0