10
Help us understand the problem. What are the problem?

posted at

updated at

Dart enum extensionは便利だぞ

はじめに

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

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を用意してあげます。

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一覧を持っていた場合。

    final articles = [
      Article(title: 'タイトル1', description: '詳細1', type: ArticleType.anime),
      Article(title: 'タイトル2', description: '詳細2', type: ArticleType.anime),
      Article(title: 'タイトル3', description: '詳細3', type: ArticleType.anime),
    ];

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

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

enumからWidgetを取得したい

そして、articlesで以下のような記事一覧画面を作るとします。

    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を追加で書いてあげたらよさそうです。

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を取得できてシュッとかけます。

    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名を省略するだけです。

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内でメソッド定義すればよいです。いい例が思いつかなかったですが、以下のようにあるパラメータを使って値を返すことができます。

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が好きになりました。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
10
Help us understand the problem. What are the problem?