GroovyでJavaScriptソースをコールしてみる2
はじめに
GroovyでJavaScriptソースをコールしてみる の続きです。
obj.get("age", obj)
のように、1回のメソッド呼び出しのために2回もオブジェクトインスタンスを記述するのが面倒です。
これをなんとかしたいと思います。
metaClass
を使って、プロパティにもっと簡単にアクセスできるようにしてみます。
metaClass
を使って、プロパティにもっと簡単にアクセスできるようにしてみる
metaClass.getAt()
メソッドを実装してやることで、Groovy内のオブジェクトに対して以下のようにプロパティアクセス可能となります。
X.metaClass.getAt = { String key -> /* any logic */ }
X x = new X()
x["some-field"]
obj.get("age", obj)
という記述を metaClass.getAt()
でくるんでやることで、 obj["age"]
のようにアクセスできるようにしてやろうと思います。
その前に寄り道。取得できたJavaScriptのオブジェクトってどんなJavaクラスなの?
これを知らなくても metaClass.getAt
に設定するクロージャ処理は実装可能ですが、
寄り道して、JavaScript実行結果から取得されたオブジェクトのクラスを調べてどのようにプロパティ情報が格納されているのかを調べてみることにしました。
import javax.script.*;
def engine = new ScriptEngineManager().getEngineByName("JavaScript");
engine.with {
eval("var genzou = {age:29, sex:'man'};");
def obj = eval("genzou")
println obj.properties
}
プロパティをすべて舐めて出力してみました。
結果、以下のように。
["allIds":["age", "sex"], "parentScope":com.sun.script.javascript.RhinoTopLevel@1feaf06, "ids":["age", "sex"], "sealed":false, "class":class sun.org.mozilla.javascript.internal.NativeObject, "className":"Object", "maxInstanceId":0, "prototype":[object Object]]
なんか難しそうだw。
allIds
って何だ??ids
との違いは分からないが、多分一緒かな。class
がsun.org.mozilla.javascript.internal.NativeObject
であることだけははっきりしました。- sun と mozilla ってどっちなんだろう(笑)
本題に戻って、 metaClass.getAt
に設定するクロージャ処理を実装
本題に戻ります。 NativeObject
クラスの metaClass
プロパティに getAt
メソッドを追加してみる。
import javax.script.*;
def engine = new ScriptEngineManager().getEngineByName("JavaScript");
engine.with {
eval("var genzou = {age:29, sex:'man'};");
// 拡張してみる
sun.org.mozilla.javascript.internal.NativeObject.metaClass.getAt = { String key -> delegate.get(key, delegate) }
def obj = eval("genzou")
println obj["age"]
}
出力結果は 「29.0」
。おおーーできたよ!やった。
いくつか分かったことが。callしたJavaScriptの結果が数値の場合には、 Double型で返ってくる みたい。それから、今回は Rhino を使用していないですが、Rhinoを使用した場合には sun.org.mozilla.javascript.internal.NativeObject の部分が org.mozilla.javascript.NativeObject となるみたいです。 sun のJavaScript実装と、 Rhino のJavaScript実装の2つがあるんですね。知らずに組むと混乱しそう。
ひとこと
できれば、 getAt
メソッドを使用せず、 println obj.age みたいにプロパティ参照形式で記述したい・・・
更に続きます。
ディスカッション
コメント一覧
まだ、コメントがありません