Haxe入門 / Anonymous Structure
2.5 Anonymous Structure 無名構造体
今更だけど訳語は調べずにつけてます。
構造体を使えばデータをひとつのまとまりにできます。 無名構造体とは、明示的に型を定義せずに構造体を作る機能です。
次の例では、x
とname
というフィールドを持ち、それぞれ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コンパイラはpoint
がFloat
型のフィールドx, y
を持つことを知ってるってことです。同時にpoint
がz: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.field
とReflect.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
を使ってx
とy
というInt
型のフィールド変数を持つPoint
という型を定義してます。
typedef Point = { var x : Int; var y : Int; }
2.5.4 Impact on Performance パフォーマンスへの影響
(2.5.3はどこ行った?)
構造体や、構造的部分型は動的型言語へのコンパイルではパフォーマンスへの影響はありません。しかし静的型言語に対しては実行時名前解決(dynamic lookup)が行われるため、大抵は静的フィールドへのアクセスよりも遅くなります。