😑

sealed classを探求してるんだけど

2024/04/17に公開

🤔やってみたいこと

Kolitnのsealed classみたいなことをしてみたいのだが、そもそも別もんなので参考にならなかった💦
以前から、役に立たない記事を書いて色々試しているのだけど、分かったことは、abstract classとして、扱われるらしくインスタンス化できないもんだってことは理解した。

いつもsealed class & switch の組み合わせで何かを作ろうとするのだが、毎回これが正解なのだろうか?
finalでプロパティを与えたりすることがあるけど、今回は、ゲッターを使ってみた。

🚀やってみたこと

このコードでは、ColorType sealed class にcolorというMaterialColorを返すゲッターを定義し、Green、Blue、Redクラスでそれをオーバーライドして各色を返すようにしています。そして、Containerの色を設定する際には、現在の色のcolorプロパティを使用しています。

import 'package:flutter/material.dart';

sealed class ColorType {
  MaterialColor get color;
}

class Green extends ColorType {
  
  MaterialColor get color => Colors.green;
}

class Blue extends ColorType {
  
  MaterialColor get color => Colors.blue;
}

class Red extends ColorType {
  
  MaterialColor get color => Colors.red;
}

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

  
  State<ToggleColorView> createState() => _ToggleColorViewState();
}

class _ToggleColorViewState extends State<ToggleColorView> {
  ColorType color = Green();

  final List<ColorType> colors = [Green(), Blue(), Red()];

  void toggleColor() {
    setState(() {
      int currentIndex = colors.indexWhere((c) => c.runtimeType == color.runtimeType);
      color = colors[(currentIndex + 1) % colors.length];
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Toggle Color...."),
        centerTitle: true,
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          GestureDetector(
            onTap: toggleColor,
            child: Container(
              color: color.color,
              height: 100,
              width: 100,
            ),
          ),
        ],
      ),
    );
  }
}

ColorBoxをonTapすると画面が更新され色が変化します。

🙂最後に

このtoggleColorメソッドは、現在の色を次の色に切り替える役割を果たしています。具体的な動作は以下の通りです:

  1. colors.indexWhere((c) => c.runtimeType == color.runtimeType);:この行は、現在の色(color)がcolorsリストの中で何番目に位置しているかを取得します。indexWhereメソッドは、与えられた条件を満たす最初の要素のインデックスを返します。ここでは、runtimeType(実行時の型)が現在の色と一致する要素を探しています。

  2. color = colors[(currentIndex + 1) % colors.length];:この行は、現在の色を次の色に更新します。(currentIndex + 1) % colors.lengthという計算により、colorsリストの中で次に来る色のインデックスを取得します。%はモジュロ演算子で、剰余を計算します。これにより、リストの最後の色の次はリストの最初の色に戻るようになります。

  3. setState(() {...});:このメソッドは、FlutterのStatefulWidgetで状態を更新するために使用されます。setStateを呼び出すと、Flutterはbuildメソッドを再度呼び出してウィジェットを再描画します。つまり、colorの値が更新され、その新しい値に基づいてウィジェットが再描画されます。

したがって、このメソッドが呼び出されると(例えば、ユーザーがタップしたとき)、現在の色が次の色に切り替わり、その結果が画面に反映されます。

What is runtimeType?

runtimeTypeはDartのObjectクラスに定義されているプロパティで、オブジェクトの実行時の型を返します。これは、オブジェクトが実行時にどのクラスのインスタンスであるかを判断するために使用されます。

例えば、以下のようなコードがあるとします:

abstract class Animal {}

class Dog extends Animal {}

void main() {
  Animal animal = Dog();
  print(animal.runtimeType);
}

このコードを実行すると、出力はDogになります。これは、animal変数がDogクラスのインスタンスを保持しているためです。runtimeTypeは、変数の宣言時の型(この場合はAnimal)ではなく、実際のインスタンスの型(この場合はDog)を返します。

ただし、runtimeTypeを頻繁に使用することは推奨されません。これは、コードの可読性を低下させ、型安全性を損なう可能性があるためです。また、runtimeTypeの比較はパフォーマンスに影響を与える可能性があります。

Discussion