Tuesday, January 25, 2011

インサイドGDK

GroovyにはJava Development Kit(JDK)を拡張するGroovy Development Kit(GDK)があります。GDKのおかげで、私達はJDKクラスと一緒に多くの便利なメソッドを使えます。ではそれらのメソッドはどこに定義されているのでしょうか? どうやってJDKのクラスに追加しているのでしょうか?


1つ目の疑問の答えは"org.codehaus.groovy.runtimeパッケージ下のクラス内"です。 そのクラスのうちいくつかを紹介します。


 - DefaultGroovyMethods: 汎用メソッドを定義します。但しいくつか非汎用メソッドも定義します。初期のバージョンでは、ほとんどのGDKメソッドがここに定義されており、Groovyチームはまだこれらの移動を完全には終わらせていません。
 - DateGroovyMethods: 日付/時間関連メソッドを定義します。
 - ProcessGroovyMethods: プロセス管理関連メソッドを定義します。
 - SwingGroovyMethods: Swing関連メソッドを定義します。


これらのメソッドには全てpublic static修飾子がついています。例えば、DefaultGroovyMethodsはdump()メソッドを次のように定義しています(dump()メソッドは過去のポスト、"Groovyによる汎用toString()"で紹介しました):
----
public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
    ...
    public static String dump(Object self) {
        ...
    }
    ...
}
----

2つ目の疑問の答えは少し複雑です。なぜなら正確には追加されているわけではないからです。ではどのように呼び出されているのでしょうか? 例を出して説明します。次のようにjava.net.URLクラスのオブジェクトに対しdump()メソッドを呼ぶとします:
----
def url = new URL('http://groovy.codehaus.org/')
url.dump()
----

この場合、Groovyは次の2つのステップでdump()メソッドを呼びます:


1. DefaultGroovyMethods.dump()のメタデータ(groovy.lang.MetaMethod)を持つorg.codehaus.groovy.runtime.callsite.MetaMethodSiteクラスのオブジェクトを生成します。
2. そのMetaMethodSiteオブジェクトを経由し、MetaMethodオブジェクトのinvoke()メソッドをURLオブジェクト引数とともに呼び出します。


つまり、簡単に言うとGroovyはバイトコードの生成時にurl.dump()をDefaultGroovyMethod.dump(url)に置き換えるわけです。


このMetaMethodSiteクラスはGroovyランタイム専用のクラスなので直接使うことはできません。でもがっかりしないでください。Categoriesを使えば同じことができます:
----
class MyMethods {
    public static String myDump(Object self) {
        ...
    }
}


use (MyMethods) {
    def url = new URL('http://groovy.codehaus.org/')
    url.myDump()
}
----

      

No comments:

Post a Comment