Kotlinのsealed classは、継承者の階層を制限する抽象クラスです:すべてのサブタイプは1つのファイル内に宣言する必要があります。これは、選択肢のセットが固定されている階層(例えば、状態、イベント、エラーを説明するため)に便利です:
sealed class Result { object Success : Result() data class Error(val message: String) : Result() object Loading : Result() } fun handle(result: Result) = when (result) { is Result.Success -> print("成功!") is Result.Error -> println("エラー: ${result.message}") is Result.Loading -> println("読み込み中...") }
whenとの関連: sealed classのすべてのサブタイプをwhen式で使用する場合、コンパイラは完全性(選択肢の網羅性)をチェックします。これにより、新しい状態を追加する際に、開発者が新しい選択肢を処理しないとコンパイルエラーが発生することが保証されます。
なぜこれは重要か:
「sealed classの継承者を異なるファイルやパッケージに配置できますか?それは型安全性にどのように影響しますか?」
回答: いいえ、sealed classのすべての直接の継承者は1つのファイル内で定義される必要があります。これは型安全性の保証のためのコンパイラの制御です。別のファイルやパッケージに継承者を配置すると、コンパイラはエラーを出します。
物語
支払いビジネスロジックの設計中に、操作結果の選択肢を追加したが、when式を更新するのを忘れた。しかし、sealed classのおかげで、コンパイラが考慮されていないケースを強調しました。別のJavaプロジェクトでは、このシナリオが初期化されていない状態を製品に持ち込むことにつながりました。
物語
プロジェクトでsealed classのデータの一部を通常のopen classに移行した結果、完全なwhenチェックが機能しなくなり、新しい状態が処理ロジックで「失われ」てしまい、インターフェースの不正な動作を引き起こしました。
物語
eコマースシステムで、sealed classの継承者を別のファイルに移動(各ファイルを再利用のためのモジュールに)してアーキテクチャを最適化しようとした。この結果、コンパイルが壊れ、リリース前の緊急リファクタリングの原因となりました。