🦂

sealed classを使ってみたい

2023/12/16に公開

Overview

https://dart.dev/language/class-modifiers#sealed
enumと同じようなものらしい...

このクラスの特徴はインスタンス化することはできない。

これはできない:

sealed class BaseDateTime {}

final d = BaseDateTime();
Abstract classes can't be instantiated.
Try creating an instance of a concrete subtype.da

翻訳すると:
抽象クラスはインスタンス化できない。
具象サブタイプのインスタンスを作成してみよう。

summary

で、早速やってみた。switch文と組み合わせて使うのが、使用例らしいので時間を扱うクラスと分岐処理を作ってみた。

sealed class BaseDateTime {}

class Year extends BaseDateTime {
  // 年を取得
  final int value;
  Year(this.value);
}

class Week extends BaseDateTime {
  // 週を取得
  final int value;
  Week(this.value);
}

class Month extends BaseDateTime {
  // 月を取得
  final int value;
  Month(this.value);
}
// switch文で型を判定して、値を取得する
int getYear(BaseDateTime dateTime) {
  switch (dateTime.runtimeType) {
    case Year:
      return (dateTime as Year).value;
    case Week:
      return (dateTime as Week).value;
    case Month:
      return (dateTime as Month).value;
    default:
      throw Exception('Invalid type');
  }
}

void main() {
  final year = Year(DateTime.now().year);
  final week = Week(DateTime.now().weekday);
  final month = Month(DateTime.now().month);
  print(getYear(year));// 2023
  print(getYear(week));// 6
  print(getYear(month));// 12
}

⏰時間の扱いについて:

YearとかWeekをつけると、データ型がintになるので、ここは注意が必要で作る処理によっては、castが必要な場面が出てきます。最近ストップウォッチの機能の開発に携わって気づきましたね。

thoughts

あまり使用例がないので、探究心で時間を扱うロジックを作ってみました。enumで似たようなものを作ろうとしたのですが、こちらは知識不足なのかいい感じのプログラムが作れなかったですね😅

おまけ

enumでも似たようなものを作ろうとしたのですが、もうちょっと改良が必要なのかうまくいかないですね。enumって実は、implementsをつけて抽象クラスを継承できるみたいです。
@overrideつけないと、継承ができないのでここは注意が必要。

https://dart.dev/language/enums

enum DateTime implements Comparable<DateTime> {
  YEAR(year: 2021, week: 1, month: 1, day: 1),
  WEEK(year: 2021, week: 1, month: 1, day: 1),
  MONTH(year: 2021, week: 1, month: 1, day: 1),
  DAY(year: 2021, week: 1, month: 1, day: 1);

  const DateTime({
    required this.year,
    required this.week,
    required this.month,
    required this.day,
  });

  final int year;
  final int week;
  final int month;
  final int day;

  
  int compareTo(DateTime other) => year - other.year;
}

void main() {
  final year = DateTime.YEAR.year;
  final week = DateTime.WEEK.week;
  final month = DateTime.MONTH.month;
  final day = DateTime.DAY.day;
  print(year);
  print(week);
  print(month);
  print(day);
}

Discussion