Dart enum extensionは便利だぞ

# はじめに

例えばこんなModelがあったとき。

```dart
class Article {
  const Article({
    required this.title,
    required this.description,
    required this.type,
  });

  final String title;
  final String description;
  final ArticleType type;
}

enum ArticleType {
  news, // ニュース
  sport, // スポーツ
  entertainment, // エンタメ
  fashion, // ファッション
  anime, // アニメ
}
```

# enumからStringを取得したい
UIで、 `ArticleType`によってその `ArticleType`名を表示したくなったとします。

そのとき、以下のようなenumのextensionを用意してあげます。

```dart
extension ArticleTypeExt on ArticleType {
  String get name {
    switch (this) {
      case ArticleType.news:
        return 'ニュース';
      case ArticleType.sport:
        return 'スポーツ';
      case ArticleType.entertainment:
        return 'エンタメ';
      case ArticleType.fashion:
        return 'ファッション';
      case ArticleType.anime:
        return 'アニメ';
    }
  }
}
```

そうすることで、Widget側で以下のような`Article`一覧を持っていた場合。

```dart
    final articles = [
      Article(title: 'タイトル１', description: '詳細１', type: ArticleType.anime),
      Article(title: 'タイトル２', description: '詳細２', type: ArticleType.anime),
      Article(title: 'タイトル３', description: '詳細３', type: ArticleType.anime),
    ];

```

こんな感じでenumのextensionを使って`ArticleType`によって欲しい `ArticleType`名を表示できます。

```dart
    final articleTypeName = articles.first.type.name; // アニメ
```


# enumからWidgetを取得したい
そして、`articles`で以下のような記事一覧画面を作るとします。

```dart
    return MaterialApp(
      title: 'Flutter Demo',
      home: ListView.builder(
        padding: const EdgeInsets.all(8),
        itemCount: articles.length,
        itemBuilder: (BuildContext context, int index) {
          final article = articles[index];
          return Column(
            children: [
              Text(article.title),
              Text(article.description),
            ],
          );
        },
      ),
    );
```

そこで、`article.type`によってリストのアイテムの中に表示する記事タグバッジWidgetみたいなものを出し分けたいときはこんな感じのWidgetを返すgetterを追加で書いてあげたらよさそうです。

```dart
extension ArticleTypeExt on ArticleType {
  String get name {
    switch (this) {
      case ArticleType.news:
        return 'ニュース';
      case ArticleType.sport:
        return 'スポーツ';
      case ArticleType.entertainment:
        return 'エンタメ';
      case ArticleType.fashion:
        return 'ファッション';
      case ArticleType.anime:
        return 'アニメ';
    }
  }

  // ↓追加
  Widget get tagBadge {
    switch (this) {
      case ArticleType.news:
        return Container(); // ニュースのときのタグバッジ
      case ArticleType.sport:
        return Container(); // スポーツのときのタグバッジ
      case ArticleType.entertainment:
        return Container(); // エンタメのときのタグバッジ
      case ArticleType.fashion:
        return Container(); // ファッションのときのタグバッジ
      case ArticleType.anime:
        return Container(); // アニメのときのタグバッジ
    }
  }
}
```

使うときは、 `article.type.tagBadge`するだけで `ArticleType`ごとの欲しいWidgetを取得できてシュッとかけます。

```dart
    return MaterialApp(
      title: 'Flutter Demo',
      home: ListView.builder(
        padding: const EdgeInsets.all(8),
        itemCount: articles.length,
        itemBuilder: (BuildContext context, int index) {
          final article = articles[index];
          return Column(
            children: [
              Text(article.title),
              Text(article.description),
              article.type.tagBadge, // 追記：ArticleTypeごとのタグバッジWidget
            ],
          );
        },
      ),
    );
```

# privateでenumのextensionを定義したい
そのファイル内でしか使わないので、extensionを外に公開したくない場合は以下のように書けばprivateになります。extension名を省略するだけです。

```dart
extension on ArticleType {
  String get name {
    switch (this) {
      case ArticleType.news:
        return 'ニュース';
      case ArticleType.sport:
        return 'スポーツ';
      case ArticleType.entertainment:
        return 'エンタメ';
      case ArticleType.fashion:
        return 'ファッション';
      case ArticleType.anime:
        return 'アニメ';
    }
  }
}

```

# extension内でメソッド定義
extension内でgetter以外に、なにか他のパラメータを使って値を返したいときはextension内でメソッド定義すればよいです。いい例が思いつかなかったですが、以下のようにあるパラメータを使って値を返すことができます。

```dart
extension on ArticleType {
  String name(int articleCount) {
    switch (this) {
      case ArticleType.news:
        return 'ニュース($articleCount)';
      case ArticleType.sport:
        return 'スポーツ($articleCount)';
      case ArticleType.entertainment:
        return 'エンタメ($articleCount)';
      case ArticleType.fashion:
        return 'ファッション($articleCount)';
      case ArticleType.anime:
        return 'アニメ($articleCount)';
    }
  }
}

```

# おわり
地味に使うDartのenum extensionの便利な書き方と使い方を紹介しました。
これで少しDartが好きになりました。