LoginSignup
27
17

More than 1 year has passed since last update.

Dart enum extensionは便利だぞ

Last updated at Posted at 2021-08-14

はじめに

例えばこんな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が好きになりました。

27
17
1

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
27
17