👨💻
# Flutter3(Dart3)で、Swiftの値付きEnumを実現したい
Flutter3(Dart3)で、Swiftの値付きEnumを実現したい
Swiftのenumの値付きenum 「正式名称 associated Value」を、Flutterでも使いたく、Flutter3からの「sealed class」を使えば、同じ表現(※)を、実現できるのでその実装MEMOです。
※...switch文に対応し、個別に値を持たせられること
// 値付きenumの例
// これと同じ表現(※)を、Flutterで実現していきます。
// タップされた種別のenum定義
enum HogeScreenAction {
// 閉じるボタン
case CloseButton
// 下部ボタン
case ButtomButton(hogeCount: Int)
// 送信ボタン
case PostButton(text: String, id: Int)
}
Flutter3(Dart3)からの機能を使えば、Swiftの値付きenumを実装できるので、そのコードを実装します。
Swiftのenumに比べると、冗長にはなりますが、Swiftと同じ実装(switch分に対応、別々の型で値を自由に設定できる)が実現できたので、使っています。
(今後、Swiftなみに、手軽に定義できればよいのですが)
Flutterでの、Swiftの値付きenum の実現
注意点
- 1, コード量が多くなる
- 2, グローバルなスコープになる
1については、Swiftのenumと同じ表現を実装する場合、enumではなくclassを使うため、
その分定義するコードが多くなります。
ただ、一度定義してしまえば、利用側のコードでは、大差ないため、
利用できるケースが多いかと思います。
2については、Swiftだと、クラス内にenum定義することができますが、
Flutterではクラスをつかうため、スコープがグローバルになり、
その分、enum名が長くなります。
必要な対応
enumと各caseの定義(sealedクラス利用)
- 1 sealedクラスで、共通クラスとして、定義する(Swiftのenum名)
- 2 sealedクラスを継承して、各enumのケースを定義(Swiftの各case名)
- 値を持たせたい場合、変数を定義して持たせる
/// - 1 sealedクラスで、共通クラスとして、定義する(Swiftのenum名)
/// sealed classで、「Swiftのenum名」として定義
sealed class HogeScreenAction {
const ButtonTapAction._();
}
/// - 2 sealedクラスを継承して、各enumのケースを定義(Swiftの各case名)
// 閉じるボタン
class HogeScreenAction_CloseButton implements HogeScreenAction {
const HogeScreenAction_CloseButton();
}
// 下部ボタン
class HogeScreenAction_BottomButton implements HogeScreenAction {
// - 値を持たせたい場合、変数を定義して持たせる
const HogeScreenAction_BottomButton({required this.hogeCount});
final int hogeCount;
}
// 送信ボタン
class HogeScreenAction_PostButton implements HogeScreenAction {
// - 値を持たせたい場合、変数を定義して持たせる
const HogeScreenAction_PostButton({required this.text, required this.id});
final String text;
final int id;
}
Switch文での利用例
UI側で、State(状態変数)を更新やロジックを書いていたが、それを、UIから切り離してAction内に集約するよう修正した際のコード例。
- switch文で値を取り出して利用
// UI側からは、.sendAction( HogeScreenAction_CloseButton() ); とコールして実装。
sendAction({required HogeScreenAction action}) async {
// MEMO: 発火したアクション名をPrint()で確認
print("[Action]---");
print(action.runtimeType);
print("-----------");
switch (action) {
case HogeScreenAction_CloseButton(): // 閉じるボタン
// TODO: stateを操作
break;
case HogeScreenAction_BottomButton(hogeCount: final hogeCount): // 下部ボタン
// TODO: stateを操作
break;
case HogeScreenAction_PostButton(text: final text, id: final id): // 送信ボタン
// TODO: stateを操作
break;
}
}
Discussion