🛡️

普段書いてるコードにsealed classを使ってみる

2024/03/09に公開

📕Overview

https://dart.dev/language/branches
sealed classとは何か?
Enumのような使い方ができるコードですね。今回だと、ただテキストを表示するのに使うだけなんですけど、sealed classって出たばかりで使用例があまりないので、興味があって色々試しているところですね。
switch文を使って、パターンマッチなるものと組み合わせて使うことが多いようですね。

Dartのクラスは、暗黙的にインターフェースがあるそうです。何も書いてなくても使えるのってそれが理由...
今回は、abstract String messageというのを定義して、継承したクラスでオーバーライドして、分岐処理によって表示するテキストを代入しています。

sealed class AppState {
  abstract String message;
}

class Loading extends AppState {

  
  String message = 'Loading...';
}

class Faire extends AppState {

  
  String message = 'Error!';
}

class Success extends AppState {

  
  String message = 'Success!';
}

🧷summary

今回はただローディングする処理がボタンを押すと実行されて、処理によってsealed classで作ったテキストを表示するすごくシンプルなものになってます。riverodもAPIも使ってないので、Faireは使う機会が実はなくて面白くないかもです。
throwで例外処理発生させたら、使えると思ったがアプリがクラッシュしました😇

こんな感じのコードを使います。main.dartでimportして使ってみてください。

import 'package:flutter/material.dart';

sealed class AppState {
  abstract String message;
}

class Loading extends AppState {

  @override
  String message = 'Loading...';
}

class Faire extends AppState {

  @override
  String message = 'Error!';
}

class Success extends AppState {

  @override
  String message = 'Success!';
}

class AppStateView extends StatefulWidget {
  const AppStateView({super.key});

  @override
  State<AppStateView> createState() => _AppStateViewState();
}

class _AppStateViewState extends State<AppStateView> {

  // 分岐処理のところで、ロード中、エラー、成功のテキストを表示する
  String switchState(AppState appState) => switch (appState) {
    Loading loading => loading.message,
    Faire faire => faire.message,
    Success success => success.message,
  };

  // ボタンを押すと、3秒後にFutureBuilderが再構築される
  Future<void> load() async {
    await Future.delayed(const Duration(seconds: 3));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.refresh),
        onPressed: () async {
          setState(() {
            load();
          });
        },
      ),
      // ボタンを押すと、load()が実行されFutureBuilderが再構築される
      body: FutureBuilder<void>(
        future: load(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: Text(switchState(Loading()), style: const TextStyle(fontSize: 30, color: Colors.blueAccent)));
          } else if (snapshot.hasError) {
            return Center(child: Text(switchState(Faire()), style: const TextStyle(fontSize: 30, color: Colors.redAccent)));
          } else {
            return Center(child: Text(switchState(Success()), style: const TextStyle(fontSize: 30, color: Colors.greenAccent)));
          }
        },
      ),
    );
  }
}

こんな感じのものができました💡

🧑‍🎓thoughts

今回は、sealed class使って、ローディングと成功の場合に異なるテキストを表示するのをやってみました。他にも良い活用方法ないかな〜と探求してるところですね。今回は、Enumの代わりに使って、分岐処理を書いたようなもんですね。

Discussion