hamburger-tech-nits

主にプログラミングのNITSな話

FreezedのUnionの共通フィールドをInterfaceで表現する

pub.dev

やりたいこと

Kotlinのsealed classでは、共通のフィールドをabstractで定義して子クラスに対して実装を強制できる。大量のフィールドを持つモデルクラスをtypeごとに分割した時など、これによって子クラスの実装漏れをビルドのタイミングで検知できるようになる。

sealded class MobileOS {
  abstruct val device: String
  object iOS: MobileOS() {
    override val device = "iPhone" // overrideでの実装を強制している
  }
  data class Android(
    override val device,
  ): MobileOS()

}

kotlinlang.org

FlutterのFreezedでは、sealed class的なものをUnionとして定義する仕組みが備わっている。そこに共通フィールドの実装を強制する仕組みが無いか調べた

実装方法

abstract classで実装を強制したいフィールドを宣言する。

abstract class GeographicArea {
  int get population;
  String get name;
}

実装を強制したいUnionに対して@Implements<>()の宣言を追加し、フィールドを定義する。宣言を記述しているのにも関わらずフィールドが不足している場合、自動生成されたクラスがエラーを吐くため検知できる。

@freezed
class Example with _$Example {
  const factory Example.person(String name, int age) = Person;


  @Implements<GeographicArea>()  // 必要なUnionに対して宣言を追加する
  const factory Example.city(String name, int population) = City;  // 宣言されたUnionは、必要なフィールドが存在しないとエラーになる
}

個人的には、freezedクラスの配下のUnionに一括で宣言するオプションがあれば助かるのと、Unionを見ただけでabstractフィールドなのか独自フィールドなのか区別できるようなアノテーションを追加する記述になってほしい。