Toolkit for CreateJS & Haxe : パッケージ名取得からのクラス生成処理共通化
Action Script 3.0(AS3) では getQualifiedClassName メソッドや describeTypea メソッドを用いる事で、インスタンスやクラスのパッケージ名を取得できます。Haxe ではどうすればよいかと調べた所、Type.getClass メソッドや Type.getClassName メソッドを用いればよいとの事です。
この Haxe によるパッケージ名を取得する方法を用い、Toolkit for CreateJS から出力されたクラスのインスタンス化を行う共通処理のメモを記述します。
仕様確認
以下の様な fla ファイルを作成したとします。
Toolkit for CreateJS を用いてこの fla ファイルをパブリッシュすると、「shooting.player.View」クラスは「lib.shootingplayerView」というクラスに変換されます。パッケージ名を区切るピリオド(.)が無くなり一文字に繋がっていることがわかります。
Haxe からは js.Lib.eval メソッドを用い以下の様な記述を行うことで lib.shootingplayerView の生成が可能となります。
var view:Container = Lib.eval("new lib.shootingplayerView()");
開発を進めていくと、パッケージ構造やクラス名に変更がかかる場合があり、その都度 shootingplayerView の記述を変更する必要があります。この修正をもう少し簡単に行えるよう、今回 Instance.hx というサンプルクラスを作成しました。
Instance.hx の使い方
まずは、Flash 側で設定したパッケージ構造 shooting.player.View クラスと同じパッケージ構造の shooting.player.Player クラスを Haxe で作成します。
作成後、Player クラス内で以下のように Instance クラスを利用する事で、lib.shootingplayerView クラスの生成が可能となります。
Player.hx
package shooting.player; import createjs.easeljs.Container; import lib.toolkit_for_createjs.Instance; class Player { private var view:Container; public function new(){ view = Instance.createWithSamePackageInstance("View", this); //view = Instance.createWithSamePackageClass("View", Player); } }
インスタンス(this) or クラス(Player) と同一パッケージ内の View クラス(lib.shootingplayerView)を生成する、という命令となります。
クラスの内容
Instance.hx では別途作成した ClassUtil.hx を利用しています。
Toolkit for CreateJS から出力されたクラスを Haxe にてインスタンス化する Instance.hx
package lib.toolkit_for_createjs; import js.Lib; import lib.utils.ClassUtil; class Instance { private static inline var NAMESPACE_SYMBOL = "lib"; public static function createWithSamePackageInstance( createdClassName:String, samePackageInstance:Dynamic, ?symbolNameSpace:String):Dynamic{ var packageNames = ClassUtil.getPackageNamesWithInstance(samePackageInstance); return create(createdClassName, packageNames, symbolNameSpace); } public static function createWithSamePackageClass( createdClassName:String, samePackageClass:Class<Dynamic>, ?symbolNameSpace:String):Dynamic{ var packageNames = ClassUtil.getPackageNamesWithClass(samePackageClass); return create(createdClassName, packageNames, symbolNameSpace); } public static function create(createdClassName:String, packageNames:Array<String>, ?symbolNameSpace:String):Dynamic{ if(symbolNameSpace == null) symbolNameSpace = NAMESPACE_SYMBOL; return Lib.eval([ "new ", symbolNameSpace, ".", packageNames.join(""), createdClassName, "()" ].join("")); } }
インスタンス or クラスからパッケージ名を取得する ClassUtil.hx
package lib.utils; class ClassUtil { public static function getPackageNamesWithInstance(instance:Dynamic):Array<String>{ var cls:Class<Dynamic> = Type.getClass(instance); return getPackageNamesWithClass(cls); } public static function getPackageNamesWithClass(cls:Class<Dynamic>):Array<String>{ var className = Type.getClassName(cls); var packageNames = className.split("."); packageNames.pop(); return packageNames; } }
開発体制やコーディングスタイルにより、同一パッケージ内のクラスインスタンス生成だけでは機能が足りない場合、処理を付け足していく必要があります。