0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Dart】enum と「拡張列挙(Enhanced Enums)」完全ガイド(Dart 2.17〜)

Posted at

はじめに

Dart 2.17 以降、enum が大幅に進化しました。
単なる「定数の集まり」ではなく、クラスのようにプロパティやメソッドを持つことができるようになっています。

この記事では、旧来の enum との違いと、新しい「拡張列挙」の活用法を整理します✨


1. そもそも enum とは?

旧バージョン(Dart 2.16 以前)

Dart の enum は、単に「名前付き定数」を定義する仕組みでした。

enum Color {
  red,
  green,
  blue,
}

void main() {
  print(Color.red); // Color.red
  print(Color.values); // [Color.red, Color.green, Color.blue]
}

特徴

  • Color.red のように呼び出す
  • values で全列挙を取得できる
  • ただし、フィールドやメソッドは持てない

2. Dart 2.17 〜「拡張列挙(Enhanced Enums)」登場!

Dart 2.17 からは、enumクラスのように扱えるようになりました。
つまり、プロパティ・メソッド・コンストラクタ・インターフェース実装が可能です!


例:プロパティ付きの拡張列挙

enum Color {
  red(0xFF0000),
  green(0x00FF00),
  blue(0x0000FF);

  // プロパティ
  final int hex;

  // コンストラクタ
  const Color(this.hex);

  // メソッド
  void describe() {
    print('Color: $name (#${hex.toRadixString(16)})');
  }
}

void main() {
  Color.red.describe(); // Color: red (#ff0000)
  print(Color.green.hex); // 65280
}

ポイント

  • ;(セミコロン)が列挙値の後に必要
  • final フィールドを定義できる
  • コンストラクタを const で指定可能
  • メソッドを定義できる
  • nameindex プロパティも利用可能

3. 実装型(インターフェース)も指定できる

拡張列挙は、implements を使ってインターフェースを実装することもできます。

abstract class Describable {
  String describe();
}

enum VehicleType implements Describable {
  car('Four wheels'),
  bike('Two wheels');

  final String info;
  const VehicleType(this.info);

  @override
  String describe() => 'Vehicle: $name, info: $info';
}

void main() {
  print(VehicleType.car.describe());
  // => Vehicle: car, info: Four wheels
}

→ クラスのように「契約を守る列挙型」が作れる!


4. メソッドやゲッターも活用できる

例:条件分岐を内包する enum

enum Planet {
  mercury(3.303e+23, 2.4397e6),
  earth(5.976e+24, 6.37814e6),
  mars(6.421e+23, 3.3972e6);

  final double mass;   // kg
  final double radius; // meters
  const Planet(this.mass, this.radius);

  double get surfaceGravity => 6.67300e-11 * mass / (radius * radius);
  double weight(double mass) => mass * surfaceGravity;
}

void main() {
  final earthWeight = 70;
  for (final planet in Planet.values) {
    final weight = planet.weight(earthWeight);
    print('${planet.name}: ${weight.toStringAsFixed(2)} N');
  }
}

→ 列挙型の中で、各要素ごとに物理計算を行うことが可能です。
Javaの「Enumクラス」に近い強力な表現ができるようになりました。


5. クラスとの比較

機能 通常の enum 拡張列挙 (2.17〜) クラス
定数の定義
フィールド保持
メソッド定義
コンストラクタ
インターフェース実装
継承 ✅(1つだけ)

→ 「拡張列挙」は、クラスと enum の中間に位置する機能です。


6. Flutterでの実践例

Flutterでも、この機能はよく使われています。
たとえば「テーマモード」や「ステータス」を表すときなど。

enum ThemeMode {
  light('明るいテーマ', 0xFFFFFF),
  dark('暗いテーマ', 0x000000);

  final String label;
  final int color;
  const ThemeMode(this.label, this.color);

  bool get isDark => this == ThemeMode.dark;
}
@override
Widget build(BuildContext context) {
  final theme = ThemeMode.dark;

  return Container(
    color: Color(theme.color),
    child: Text(theme.label),
  );
}

→ 文字列ラベルや色コードを直接保持できるので、
以前より enum の使い勝手が格段に上がっています。


7. switch と組み合わせて型安全に!

Dartの switch 文は、enumと非常に相性が良いです。
全ケースを網羅しないとコンパイルエラーを出せるため、安全な分岐処理が可能です。

enum Status { idle, loading, success, error }

String getMessage(Status status) {
  return switch (status) {
    Status.idle => '待機中',
    Status.loading => '読み込み中...',
    Status.success => '成功!',
    Status.error => 'エラー発生!',
  };
}

Dart 3.0 の switch 式(pattern matching)との連携も◎
enum を exhaustiveness(網羅性)チェック付きで安全に使えます。


まとめ

機能 説明
enum 定数の集まり(Dart 2.16以前)
拡張列挙 プロパティ・メソッド・コンストラクタを持つ強化版
implements インターフェース実装も可能
switch 型安全な網羅チェック付きで分岐可能

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?