sealed classとsealed interfaceはKotlinにおける制限付き型階層のメカニズムで、すべての可能なサブクラスがコンパイル時に既知となります。通常の抽象クラスとは異なり、sealed classはwhen式におけるすべてのバリアントの網羅的処理を保証します。JetBrains Kotlin Language Guide(2026)のドキュメントによると、sealed型はKotlinプロジェクトにおける状態、UI画面、結果型のモデリングの基盤です。
重要なポイント
sealed classは制約付きの抽象クラスです。すべての直接サブクラスは、sealed class自体と同じファイルで宣言されなければなりません。この制約により階層は閉じられ(sealed)、ファイル外のコードは新しいサブクラスを追加できません。
sealed interfaceはKotlin 1.5で追加され、同じ保証を提供しますが、インターフェースの柔軟性を備えています。sealed interfaceは1つのファイル内で複数のクラス、オブジェクト、または他のインターフェースによって実装できます。sealed classとは異なり、sealed interfaceには単一継承の制限がなく、クラスは複数のsealedインターフェースを同時に実装できます。
Kotlin Evolution and Roadmap(2026)によると、sealed interfaceはより柔軟なモデリングのためにコミュニティの要請により追加されました。主な動機は、多重クラス継承なしで独立した型階層を組み合わせる能力です。
sealed classの宣言は、classの前にsealed修飾子を付けて始まります。サブクラスは同じファイルで宣言されます。
sealed class NetworkResult {
data class Success(val data: String) : NetworkResult()
data class Error(val message: String) : NetworkResult()
object Loading : NetworkResult()
}
sealed classの各サブクラスは、独自のプロパティとメソッドを持つことができます。Loadingはシングルトン(object)、SuccessとErrorはパラメータ付きのdataクラスです。コンパイラは3つのバリアントすべてを認識し、whenで使用されたときにその完全性をチェックします。
sealedクラスはネスト可能で、型安全性を失うことなく複雑なデータモデルのための多層階層を作成できます。
sealed class UiState {
object Idle : UiState()
object Loading : UiState()
data class Content(val items: List<Item>) : UiState()
data class Error(val exception: Throwable) : UiState()
}
sealed interfaceはsealed classと同様に宣言されますが、1つのクラスで複数のsealedインターフェースを実装できます。
sealed interface Action
sealed interface Loggable
data class Navigate(val route: String) : Action, Loggable
data class ShowToast(val text: String) : Action
object GoBack : Action, Loggable
Navigateクラスは2つのsealedインターフェース(ActionとLoggable)を同時に実装します。これは単一継承の制限によりsealed classでは不可能です。sealed interfaceは独立した階層を組み合わせる柔軟性を提供します。
sealed interfaceは、階層が共有状態やコンストラクタを必要としない場合に適しています。JetBrains Kotlin Guidelines(2026)によると、共通のコンストラクタが不要なすべての新しい階層ではデフォルトでsealed interfaceを使用すべきであり、将来の拡張に対してコードの柔軟性が高まります。
sealed型の主な利点は、when式における網羅的(exhaustive)処理です。コンパイラはすべての可能なサブクラスがカバーされているかをチェックします。
fun handleResult(result: NetworkResult): String = when (result) {
is NetworkResult.Success -> "Data: ${result.data}"
is NetworkResult.Error -> "Error: ${result.message}"
is NetworkResult.Loading -> "Loading..."
// elseは不要 — コンパイラはすべてのバリアントがカバーされていることを認識している
}
もし開発者がsealed階層に新しいサブクラスを追加したが、whenでの処理を忘れた場合、コンパイラはエラーを出します。これは型レベルでの安全性であり、else分岐を使用するオープンな階層では利用できません。
Google Android Developers(2026)によると、sealedクラスはJetpack ComposeでUI状態をモデル化する推奨方法です。whenの網羅的チェックにより、開発者が画面のすべての可能な表示バリアントを処理していない状態を防ぎます。
enum classとsealed classはしばしば混同されますが、異なる目的と機能を持ちます。
| 特徴 | sealed class | enum class |
|---|---|---|
| インスタンス | 複数(data class)、単一(object) | 定数ごとに1つ |
| プロパティ | 各サブクラスで異なる | すべての定数で同じ |
| 継承 | 可(sealed classから) | 不可(暗黙的にfinal) |
| コンストラクタ | パラメータを持つことができる | すべての定数で共通のみ |
| 階層 | 制限付き、sealed | 固定された定数セット |
sealed classとenum classの選択はタスクに依存します。バリアントが追加データを持たない場合はenumを使用します。各バリアントが一意のフィールドを含む場合はsealed classまたはsealed interfaceを使用します。
sealed型は、型安全なモデリングが必要な一連の標準シナリオでKotlinプロジェクトに使用されます。
各Compose画面は、すべての可能な状態(Idle、Loading、Content(data)、Error(exception))を記述するsealed class UiStateを持つことができます。when式によりすべての状態が処理されることが保証されます。
NetworkResult(Success、Error、Loadingのバリアント)は、RetrofitやKtorを使用するKotlinプロジェクトの標準パターンです。sealed classは各リクエスト結果の安全な処理を保証します。
sealed interfaceを用いたナビゲーションルートにより、モジュールは統一された階層内にとどまりながら独自のルートを宣言できます。これによりコンパイル時に未知のルートに関するエラーが排除されます。
KotlinConf(2025)によると、sealed classとsealed interfaceはモダンなKotlinアプリケーションにおける型安全設計の基盤です。これらはdata classと組み合わされて、コンパイル時の安全性を失うことなく複雑なドメイン構造をモデル化します。
よくある質問
sealed classのすべての直接サブクラスは同じファイルで宣言されなければなりません。sealed interfaceにも同じルールが適用されます。実装は1つのファイルにまとめます。
いいえ、単一ファイルのルールはsealed interfaceにも適用されます。すべての実装はsealed interfaceが宣言されたファイルになければなりません。
sealed interfaceは状態やコンストラクタを持たず、複数の実装を許可します。sealed classはコンストラクタと共有状態を持つことができますが、クラスは1つのsealed classしか継承できません。
コンパイラがwhenの完全性をチェックします。すべてのサブクラスが処理されていない場合、コードはコンパイルされません。これにより実行時エラーが排除され、コードの安全性が向上します。
はい、sealed classはコンストラクタを持つことができます(デフォルトでプライベート)。すべてのサブクラスはsuper()を介してこのコンストラクタにパラメータを渡せます。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。