続 JavaFX のリフレクション
今回もリフレクションの勉強です。
次のプログラムはオブジェクトのメンバー(フィールド、メソッド)に対する基本的なアクセスを行います。
プログラム例その3
package fooami; import javafx.reflect.*; /** * リフレクションによるオブジェクトのメンバーアクセス。 * @author hide1080 */ function run(args: String[]) { // Foo オブジェクトを生成 var who = Foo {}; println(who); // カレントVM の FXContext (実装クラスは FXLocal.Context) の // シングルトンインスタンスを取得 var context = FXLocal.getContext(); // Foo に対する FXClassType と FXObjectValue を取得 var clazz = context.findClass("fooami.MemberReflection$Foo"); var objValue = context.mirrorOf(who); // FXVarMember を介して Foo オブジェクトの name フィールドを変更 var varMember = clazz.getVariable("name"); varMember.setValue(objValue, context.mirrorOf("Gonbe")); println(who); // FXFunctionMember を介して Foo オブジェクトの setName() メソッドを実行 var fncMember = clazz.getFunction("setName", context.getStringType()); fncMember.invoke(objValue, context.mirrorOf("Foo am I?")); println(who); // FXObjectValue の invoke() メソッドでも実行できる objValue.invoke(fncMember, context.mirrorOf("hide1080")); println(who); } class Foo { var name = "Nanasi"; function setName(nm: String): Void { name = nm; } public override function toString(): String { return "Foo: {name}"; } }
プログラム例その3の結果
c:\WORK\fx>javafxc fooami\MemberReflection.fx c:\WORK\fx>javafx fooami.MemberReflection Foo: Nanasi Foo: Gonbe Foo: Foo am I? Foo: hide1080
次は Jim おじさんのエントリをヒントに書いたプログラムです。
プログラム例その4
package fooami; import javafx.reflect.*; /** * リフレクションによる Stage, Scene, Text の作成。 * @author hide1080 */ function run(args: String[]) { // カレントVM の FXContext (実装クラスは FXLocal.Context) の // シングルトンインスタンスを取得 var context = FXLocal.getContext(); // リフレクションで javafx.scene.text.Text を作成 var clazz = context.findClass("javafx.scene.text.Text"); var objValue = clazz.allocate(); objValue.initVar("x", context.mirrorOf(30.0)); objValue.initVar("y", context.mirrorOf(30.0)); objValue.initVar("content", context.mirrorOf("Hello, Reflection's World!")); objValue = objValue.initialize(); var objValueText = objValue; // リフレクションで javafx.scene.Scene を作成 clazz = context.findClass("javafx.scene.Scene"); objValue = clazz.allocate(); objValue.initVar("width", context.mirrorOf(200.0)); objValue.initVar("height", context.mirrorOf(100.0)); objValue = objValue.initialize(); // initVar でシーケンスタイプのフィールドを初期化しようとすると // 内部で FXLocal.SequenceValue から FXLocal.ObjectValue への ClassCastException // となってしまうので FXVarMember を介してシーケンスを設定するようにした var seqValue = context.makeSequence(objValueText.getType(), objValueText); var varMember = clazz.getVariable("content"); varMember.setValue(objValue, seqValue); var objValueScene = objValue; // リフレクションで javafx.stage.Stage を作成 clazz = context.findClass("javafx.stage.Stage"); objValue = clazz.allocate(); objValue.initVar("title", context.mirrorOf("Reflection Example")); objValue.initVar("scene", objValueScene); objValue = objValue.initialize(); var stage = (objValue as FXLocal.Value).asObject(); return stage; }
プログラム例その4の結果
見ての通りですがやっぱりリフレクションを使用すると冗長で複雑なプログラムになってしまいます。
一般のアプリケーションで使用することは殆ど無いでしょう。
僕もまだあまりよく見えていませんが、JavaFX において、用途としてはツールや特殊なライブラリ、実行時の状態の監視などとなるでしょうか。