Haxe enum を使ってみる
「Haxe の enum は便利だ」とよく目にします。しかし公式の説明を見るものの、どういった場面に使えばよいのか理解できていませんでした。
Haxe: 列挙型(enum)
http://haxe.org/ref/enums?lang=jp
実際に利用してみて、きっとこういう事なのだろう、と少々理解できたので、以下にその内容を記述します。使い方が間違っていたらごめんなさい。
サンプル
一番わかりやすい簡単な利用方法としましては、「メソッドの引数に特定のデータ以外のものを指定して欲しくない場合に enum を利用する」なのではないかと考えました。
例えば以下の様な 引数に FruitKind クラスのいずれかの定数値を渡して欲しい Sample コンストラクタがあるとします。
class Sample{ public function new(fruitKind:Int){ ... } } class FruitKind{ public static var ORANGE:Int = 1; public static var APPLE:Int = 2; public static var BANANA:Int = 3; }
Main クラスからは以下のように Sample コンストラクタを呼び出します。
class Main{ public function new(){ var sample = new Sample(FruitKind.ORANGE); } }
しかし Sample コンストラクタの引数は Int 型なので、FruitKind クラスの定数値以外も指定できてしまいます。
class Main{ public function new(){ var sample = new Sample(10); //NG } }
これを何とかするために、enum を利用します。Sample クラスを以下のように修正し、FruitKind を enum 型に変更します。
class Sample{ public function new(fruitKind:FruitKind){ var fruitKindNumber = getFruitKindNumber(fruitKind); ... } privae function getFruitKindNumber(fruitKind:FruitKind):Int{ return switch(fruitKind){ case FruitKind.ORANGE: 1; case FruitKind.APPLE: 2; case FruitKind.BANANA: 3; } } } enum FruitKind{ ORANGE; APPLE; BANANA; }
Main クラスからは以下のように Sample コンストラクタを呼び出します。
class Main{ public function new(){ var sample = new Sample(FruitKind.ORANGE); } }
初めの Main クラスのソースコードと内容は変わりありませんが、Sample コンストラクタには 10 といった Int 型を指定する事はできなくなりました。FruitKind.ORANGE, FruitKind.APPLE, FruitKind.BANANA 以外は指定できません。
余談
enum を使わずに、FruitKind のみを設定するようにしたい場合、私はよく以下の様なプログラミングを行なっていました。
class Sample{ private var fruitKind:Int; public function new(){ } public function setOrange(){ fruitKind = FruitKind.ORANGE; } public function setApple(){ fruitKind = FruitKind.APPLE; } public function setBanana(){ fruitKind = FruitKind.BANANA; } } class FruitKind{ public static var ORANGE:Int = 1; public static var APPLE:Int = 2; public static var BANANA:Int = 3; }
上記のようにする事で、Main メソッドからは FruitKind クラスは import しなくてもよい、という利点?も挙げられます。
ただし、setOrange, setApple, setBanana メソッドは同じ振る舞いを行う必要があるため、仮に引数をたくさん要する場合、全てのメソッドで同じ引数を用意しなくてはならないという難点が発生します。
public function setOrange(a:Int, b:Int, c:Int, d:Int, e:Int){ fruitKind = FruitKind.ORANGE; } public function setApple(a:Int, b:Int, c:Int, d:Int, e:Int){ fruitKind = FruitKind.APPLE; } public function setBanana(a:Int, b:Int, c:Int, d:Int, e:Int){ fruitKind = FruitKind.BANANA; }
まとめ
引数に enum を指定する箇所がある場合、開発者は、enum 内のいずれかの変数を指定すればよいことがわかります。
enum を利用する事で、ドキュメント不足のライブラリ等、このメソッドの引数には何を指定すればよいのかわからない、といった事を避ける事が出来るようになりそうです。