Haxe3の実戦投入
色々技術的な事とかマネジメント的な事など書きたい事が蓄積中。本当はキチっと纏めて、前編〜中編〜後編みたいに書きたいけど、纏めるの大変だから気の向くままに書いていくね。
Haxe3の実戦投入
開発環境
Haxe3
FlashProfessionalCS6
Toolkit for CreateJS 1.2
デプロイ
FP: FlashLite2.1
iOS/Android: CreateJS
上記の構成で、Haxe3を導入。FlashLite2.1/CreateJSのデプロイをワンソースで。ひさしぶりに先端っぽい技術に触れて面白かった。あ、エディタはIntelijですよ!
FlashLite2.1/CreateJSの差異吸収
ワンソースとはいえ実際にはローレベルな差異吸収や、パフォーマンス向上といった理由からuntypedによるAS2/JSの直書き/書き分けが必要だった。
分かりやすい例は表示オブジェクトのプロパティ操作。つまりxと_xの処理分け。これは表示オブジェクトのラッパークラスを作ってgetter/setterでアクセスすればOK。もはや古典的技法と言えるかもしれない。
class DisplayObjectProxy
{
@:isVar public var x(get, set):Float;
public function get_x()
{
#if flash
return _display._x;
#elseif js
return _display.x;
#end
}
public function set_x(i:Float)
{
#if flash
return _display._x=i;
#elseif js
return _display.x=i;
#end
}
}
ただ全てのプロパティを網羅した訳ではない。rotation等は使う機会が無かったので割愛した。これは断じて手抜きではなく、Androidや非力なフィーチャフォンでのパフォーマンスを確保する為のチューニングとして削除したのだ(ほんとだってば)。
厳格な型と型推論
Haxeのシンタックス自体はAS3とほとんど一緒なので、非常に書きやすい。型が厳格と聞いて、もしやjavaの如く長ったらしいコードを書かされるのではと心配したが、全くの杞憂だった。むしろAS3より簡潔に書けるかもしれない。ここらへんは型推論による恩恵なのだろう。具体的には以下のAS3のコードが
//AS3
var hoge:String = getName();
function getName():String
{
return 'fuga';
}
↓
//Haxe
var hoge = getName(); //hoge:Stringとしない
function getName():String
{
return 'fuga';
}
となる。getName()の戻り値がStringなのでhogeの型はStringなのは自明だからだ。ただしメソッドの引数やクラスのプロパティには型指定を行うので、そこら編の使い分けに留意する必要がある。
enum
もうね、これだけでどんぶり飯3杯は!っていう機能。ASにも、いやEcmaにも早く搭載されてほしい。ここも具体的なコードでご説明。
//AS3
private static const POSITION_TYPE_TOP:int=1;
private static const POSITION_TYPE_BOTTOM:int=2;
function changePosition(var positionType:int)
{
switch( positionType ) {
case POSITION_TYPE_TOP:
y=0;
break;
case POSITION_TYPE_BOTTOM:
y=1000;
break;
}
}
}
//Haxe
enum PositionType
{
TOP;
BOTTOM;
}
function changePosition(positionType:PositionType)
{
switch( positionType ) {
case TOP:
y=0;
case BOTTOM:
y=1000;
}
}
}
enumによってマジックバリューが発生しにくくなるのが分かるはず。AS3だとchangePosition()を呼び出す際、二つの方法が可能になる、
changePosition(POSITION_TYPE_TOP); changePosition(1);しかしHaxeだと
changePosition(TOP);
しか許容されない。まじヤバイ(スバラシイ)。
余談だけど、Haxeのswitchがまたごりごりに強力。引数に渡したenumのプロパティの数だけcaseが無いとコンパイルエラー出る。後breakは無くても下のcaseに処理は下って行きません。
Reflect
唯一、ちょっとメンドイかもと思ったのがReflectクラスを使ったプロパティへのアクセス。前回のエントリーでも触れたけど、
AS/JSのコードが下記の場合
hoge['fuga']=10;Haxeはこうなる
Reflect.setProperty(hoge,'fuga',10)
タイプセーフを実現する上で必須項目なんだろうと思うし、個人的には賛成。しかしクロスコンパイル後、メソッドがネストされまくってしまうので、ボトルネックな気がする。ここは今回に限ってuntypedで直書きと臨機応変(と言う名の黒魔術)に対応した。
ざっくり書いてみたけど、まだまだHaxeビギナーなので突っ込みとか歓迎してます。

