「静的型付けが出来るJavaScriptの上位言語」を触ってみよう。パート4 - Haxe

第4回までやってまいりましたこのシリーズ

「静的型付けが出来るJavaScriptの上位言語」を触ってみて自身の感想をまとめています。

今回はHaxeです。

Haxe

http://haxe.org/?lang=jp

ってなに?

  • 「ヘックス」と発音
  • 歴史がある
    • 2005〜
  • ソースファイル(.hx)をコンパイルして様々な言語(↓Wiki参照)のソースファイルを出力
    • これが一番の特徴ではないかと思う
  • ActionScriptに似た構文

前回までのTypeScriptとは異なりJavaScript以外の言語へのコンパイルをサポートしている点がものすご~く気になる。が、今回は「JavaScriptの...」と銘打っているのでJavaScriptのみ。

その他詳細はWiki等で

本日の見出し

コンパイラインストール

Mac/WinはDLサイトにインストーラがあるのでダウンロードしてインストールする。

コマンドラインからインストールする方法は見つかりませんでした... ちなみにbrewにはない模様

コンパイルしてみる

TypeScriptのノリでコンパイルしようとしたらいろいろ躓いたので違いを列挙

  • Mainクラスが必要
    • コンパイラにMainクラスを指定しなといけないので
    • Mainクラスの名前は任意
  • クラス名とファイル名は合わせる
  • Mainクラスにはmainメソッドが必要
  • 素のJavaScriptコードはコンパイラが受け付けない

と言うわけでまずはMainクラス作成

Sample.hx

class Sample {
    static function main() {    // mainメソッド
        trace("Hello World !"); // ←コンソールへの出力はこんな風に表現する
    }
}

そしてコンパイル

$ haxe -main Sample -js sample.js

結果

sample.js

(function () { "use strict";
var Sample = function() { }
Sample.main = function() {
    console.log("Hello World !");
}
Sample.main();
})();

Haxeはコンパイルに必要な情報を1つのビルドファイルにまとめて定義することができる

こういうの好きなのでやってみる

build.hxml

-main Sample
-js sample.js
  • ファイルの内容はコンパイルオプションの列挙

コンパイルする。

$ haxe build.hxml

これでコンパイルオプションが複雑になっても面倒くさくない

クラス定義

こんな感じ

class Sample {
    static function main() {    // mainメソッド
        trace("Hello World !");
    }

    var num1 : Int;                         // プロパティ
    private var num2 = 100;                 //Constantsなら宣言と同時に初期化が可能
    // public var sample = new Sample();    //Constantsではない値での初期化はコンパイルエラー

    public function new() {     // コンストラクタ
        trace("constructor");
    }

    public function setNum2(num2: Int) {   // 引数型指定
        this.num2 = num2;
    }

    public function getNum2(): Int {    // 戻り値型指定
        // return 'hoge';   // ←はString型を返却している為コンパイルエラー
        return this.num2;   // 宣言と同時に初期化したフィールドは型が自動解決されている
    }

    /* 同名メソッドのオーバーロード定義はできない
    public function new(num1 : Int) {
        this.num1 = num1;
    }
    */
}
  • varfunctionが必ず必要なことぐらいでTypeScriptと大差無い
  • もはやLL言語とは言わせない感がある

継承

class SubSample extends Sample {
    override public function getNum2(): Int {
        return this.num2 * 2;
    }
}
  • オーバーライドする場合overrideキーワードが必ず必要

外部JavaScriptライブラリの使用

TypeScriptの宣言ソースファイルのようにexternと言う仕組みがある。

externが用意されたライブラリはもちろん型を考慮してすぐにHaxeコードに取り込める。

externが無い場合、自分で用意するか、untypedキーワードを使ってライブラリが読み込まれていることを前提としたコードを書くことになる。

上記「コンパイルしてみる」の通り、Haxeは素のJavaScriptのコンパイルは行えない。 このことからuntypedキーワードを使ってのコーディングはHaxe上ではあまり多用するものではないように感じる。

その他いろいろ

TypeScript #2で紹介したEnumsジェネリクスももちろんある。

Enum要素をオブジェクトのように扱うことができたり、先日のバージョンアップで追加された抽象型は魅力的。

詳しくは以下等を参照


ひとつの言語を語るのには全くもって情報が少なすぎるように思いますが、一旦まとめます。

一言でいうと「重厚感」。これにつきます。

TypeScriptからの流れで対応した経緯からかもしれませんが、もはやJavaScriptとは一線を画した言語であると感じました。

様々な言語へコンパイルすることが目的であれば全く問題ありませんが、今回のテーマのように「JavaScriptを静的型付けする」こと(JavaScriptの代替)が目的であれば、やや重い気もします。

特に、多くのメンバーがJavaScriptに慣れ親しんでいるようなプロジェクトだと、Haxeの重さインパクトがかなり大きいように思います。

この重さが効果を発揮するような状況ももちろんあります。

Haxeのメリットを最大限享受できるよう使い処をしっかり考えて使いたいと思います。

次回

自身の大本命Dartです。

本日参考にさせていただいたサイト

本文には載せておりませんが、いろいろ参考にさせていただきました。ありがとうございました。