Haxe入門 / Anonymous Structure

目次に戻る

2.5 Anonymous Structure 無名構造体

今更だけど訳語は調べずにつけてます。

構造体を使えばデータをひとつのまとまりにできます。 無名構造体とは、明示的に型を定義せずに構造体を作る機能です。

次の例では、xnameというフィールドを持ち、それぞれ12"foo"という値が入ってる無名構造体を作ってます。

class Structure {
    static public function main() {
        var myStructure = { x: 12, name: "foo"};
    }
}

無名構造体を作る場合の文法を説明します。

  • 構造体は{...}で囲まれる。
  • キーと値のペアはコロン:で区切られる。例) x:12
  • この(キー:値)のペアは、カンマ,で区切って複数並べることができる。
  • 値には、Haxeのどんなでも持つことができる。

最後の4つ目のルールから、無名構造体の中に無名構造体を入れ子状に作ることができます。

var user = {
    name : "Nicolas",
    age : 32,
    pos : [{ x : 0, y : 0 },{ x : 1, y : -1 }],
};

無名構造体のフィールドは、クラスの場合と同じようにドット.でアクセスできます。

user.name; // get value of name, which is "Nicolas"
user.age = 33; // set value of age to 33

もちろん無名構造体で定義されてないフィールドにはアクセスできません。あくまでもHaxeの構造体ですから。次の例はコンパイルエラーになります。

class Test {
    static public function main() {
        var point = { x: 0.0, y: 12.0 };
        point.z; // NG!
    }
}

エラーメッセージ

{ y : Float, x : Float } has no field z

このエラーメッセージが出るということは、HaxeコンパイラpointFloat型のフィールドx, yを持つことを知ってるってことです。同時にpointz:Floatというフィールドを持っていないということも。このようにHaxeコンパイラpointの型が何なのか推論します。

場合によっては、pointを他のクラスのフィールドに持ちたいこともあるでしょう。その場合は明示的にpoint無名構造体の型を書くことができます。

class Path {
    var start : { x : Float, y : Float };
    var target : { x : Float, y : Float };
    var current : { x : Float, y : Float };
}

ですがこの書き方は同じ物を何度も書かなければならないので冗長ですし、面倒くさいので普通はtypedefを使って型名を定義します。

typedef Point = { x : Float, y : Float }

class Path {
    var start : Point;
    var target : Point;
    var current : Point;
}

これですっきりしました!

2.5.1 JSON for Structure Values 構造体の値としてJSON記法を使う。

文字列リテラルをキーに使えばJavaScript Object Notaton(JSON)でも構造体を作れます。

var point = { "x" : 1, "y" : -5 };

どんな文字列リテラルでも使えますが、Haxe識別子として有効なものだけがフィールドとしてみなされます。もし識別子として正しくなければ、フィールドにアクセスできず、Reflect.fieldReflect.setFieldといったリフレクションを使わなくてはならなくなります。上の例だと、x,yはともに識別子として有効なので、

trace(point.x);

とアクセスできます。しかし、

var invalid_field = { "$": 3, "y":4 };
trace(invalid_field.$); // エラー

これはできません。$Haxeでは有効な識別子ではないからです。識別子についての記載はにあります。

2.5.2 Class Notation for Structure Types 構造体の型にクラス記法を使う

クラスの型を定義する際に、クラスフィールドと同じ文法を使えます。次の例ではtypedefを使ってxyというInt型のフィールド変数を持つPointという型を定義してます。

typedef Point = {
    var x : Int;
    var y : Int;
}

2.5.4 Impact on Performance パフォーマンスへの影響

(2.5.3はどこ行った?)

構造体や、構造的部分型動的型言語へのコンパイルではパフォーマンスへの影響はありません。しかし静的型言語に対しては実行時名前解決(dynamic lookup)が行われるため、大抵は静的フィールドへのアクセスよりも遅くなります。

目次に戻る