Dart2.17で追加されたenhanced enumsを使ってenumにFactoryコンストラクタを作成する
はじめに
最近個人開発でFlutterアプリを作っており、文字列からenumを生成したい場面があった。
これまではenumに対してExtensionを使ってメソッドを定義していたが、Dart2.17でenumが拡張されていたのを思い出し改めて調べてみるとExtensionを使わずとも実現できるようだった。個人用にまとめておく。
便利になったenum
enhanced enumsとは
まずはenhanced enumsについて軽く触れておく。公式ページにあるコードを拝借するが、以下のようにインスタンス変数やメソッド、コンストラクタをenum内に定義することができるというものだ。
enum Vehicle implements Comparable<Vehicle> {
car(tires: 4, passengers: 5, carbonPerKilometer: 400),
bus(tires: 6, passengers: 50, carbonPerKilometer: 800),
bicycle(tires: 2, passengers: 1, carbonPerKilometer: 0);
const Vehicle({
required this.tires,
required this.passengers,
required this.carbonPerKilometer,
});
final int tires;
final int passengers;
final int carbonPerKilometer;
int get carbonFootprint => (carbonPerKilometer / passengers).round();
@override
int compareTo(Vehicle other) => carbonFootprint - other.carbonFootprint;
}
ただし、いくつか制約がある。
- インスタンス変数は
final
であることが必要 - 生成コンストラクタ(
generative constructors
)はconst
であることが必要 - Factoryコンストラクタは定まったenumを返す必要がある(
null
は返せない) - 他のクラスを拡張することはできない
index
、hashCode
、==
のオーバーライドはできないvalues
という名前のメンバーは定義できない(enumによって自動で生成されるものと衝突するため)- 少なくとも一つのインスタンスが宣言の最初に定義されている必要がある
Facotryコンストラクタ
上記の公式ページには例がないが、Factoryコンストラクタも定義できる。
enum Color {
red,
blue,
none; // セミコロンであることに注意!
factory Color.from(String value) {
switch (value) {
case 'red':
return Color.red;
case 'blue':
return Color.blue;
default:
return Color.none;
}
}
}
Color.from('red') // Color.red
enhanced enumsの制約のためnull
を返すことはできないので、意図しない引数の場合はエラーを吐いたり専用のenumを返したりなど何らかの対応が必要になるので注意。
おわり
enhanced enumsによってenumがかなり便利になった。これからどんどん使っていきたいし、既存のコードもどんどん書き換えていきたい。