Haxe : メソッド同士の比較には比較演算子ではなく Reflect.compareMethods メソッドを用いる
私は変数にメソッドを代入する方法をよく用います。
例えば Acsion Script 3.0(AS3)では以下のように mainFunction という変数を用意し、コンストラクタ内で mainFunction にメソッド(の参照?) testA を代入します。、次に外部から run メソッドを定期的に呼び出す事で、testA→testB→finish といった順番でメソッドを自動的に実行させます。
//AS3 public class Sample{ private var mainFunction:Function; public function Sample(){ mainFunction = testA; } public function run():void{ mainFunction(); } private function testA():void{ mainFunction = testB; } private function testB():void{ mainFunction = finish; } private function finish():void{ } public function isFinished():Boolean{ return mainFunction == finish; } }
Sample クラスの処理終了を示す finish メソッドが実行されたかどうか判定するためには、isFinished メソッドを用います。mainFunction 変数と finish メソッドの値が等しければ終了している、としています。
ここで上記 AS3 で書かれた処理をそのまま Haxe に移植してみると以下の様になります。
//Haxe class Sample{ private var mainFunction:Dynamic; public function new(){ mainFunction = testA; } public function run(){ mainFunction(); } private function testA(){ mainFunction = testB; } private function testB(){ mainFunction = finish; } private function finish(){ } public function isFinished(){ return mainFunction == finish; } }
しかし、この Haxe プログラムを Javascript に変換してみたところ、isFinished メソッドが true を返すことはありませんでした。
Haxe から出力された Javascript 内のソースコードを見てみると、行末に .$bind(this)といった記述が追加されており、単純な変数とメソッドとの比較にはなっていない事がわかりました。
//Javascript ,isFinished: function() { return this.mainFunction == this.finish.$bind(this); }
どうしたものかと「haxe compare method」といった単語で調べてみた結果、Reflect.compareMethods メソッドというものが見つかりました。以下のように記述すれば問題は解決します。
//Haxe public function isFinished(){ return Reflect.compareMethods(mainFunction, finish); }
今回の問題は Haxe にて Dynamic 型を利用しているため発生したと言えます。AS3 で言うところの Function クラスみたいなものがあればよいのですが、Dynamic 以外にどういう記述をすればよいかの方法はまだ見つかっていません。
Haxe API のページを見てみると haxe.macro.Function というクラスがあり、これが使えるのだろうか?とも思いましたが、エラーで使うことができず。macro と書かれているので、恐らく期待しているものとは異なりそうです。