okaryo.log

Dart2.17で追加されたenhanced enumsを使ってenumにFactoryコンストラクタを作成する | okaryo.log

Dart2.17で追加されたenhanced enumsを使ってenumにFactoryコンストラクタを作成する

    #Dart

はじめに

最近個人開発で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は返せない)
  • 他のクラスを拡張することはできない
  • indexhashCode==のオーバーライドはできない
  • 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がかなり便利になった。これからどんどん使っていきたいし、既存のコードもどんどん書き換えていきたい。


関連記事
最新記事
プロモーション

This site uses Google Analytics.