Kotlinのsealed classとinterface — その概要、構文、適用

著者: IT Sectr 公開日: 2026-06-20 読了時間: 11 分

sealed classとsealed interfaceはKotlinにおける制限付き型階層のメカニズムで、すべての可能なサブクラスがコンパイル時に既知となります。通常の抽象クラスとは異なり、sealed classはwhen式におけるすべてのバリアントの網羅的処理を保証します。JetBrains Kotlin Language Guide(2026)のドキュメントによると、sealed型はKotlinプロジェクトにおける状態、UI画面、結果型のモデリングの基盤です。

重要なポイント

  • sealed — すべてのサブクラスがコンパイル時に既知となる制限付き階層
  • when — 必須のelseブロックなしですべてのサブクラスを網羅的に処理
  • sealed interface — 継承制限なしの柔軟な階層のためにKotlin 1.5で追加
  • コンパイル — sealed型に対する不完全なwhenでコンパイルエラー
  • 階層 — すべてのサブクラスは同じファイルまたはsealedクラス内になければなりません

sealed classとsealed interfaceとは?

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の構文

sealed classの宣言は、classの前にsealed修飾子を付けて始まります。サブクラスは同じファイルで宣言されます。

kotlin
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クラスはネスト可能で、型安全性を失うことなく複雑なデータモデルのための多層階層を作成できます。

kotlin
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の構文(Kotlin 1.5+)

sealed interfaceはsealed classと同様に宣言されますが、1つのクラスで複数のsealedインターフェースを実装できます。

kotlin
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 classの代わりにsealed interfaceを選ぶ場合

sealed interfaceは、階層が共有状態やコンストラクタを必要としない場合に適しています。JetBrains Kotlin Guidelines(2026)によると、共通のコンストラクタが不要なすべての新しい階層ではデフォルトでsealed interfaceを使用すべきであり、将来の拡張に対してコードの柔軟性が高まります。

whenにおける網羅的処理

sealed型の主な利点は、when式における網羅的(exhaustive)処理です。コンパイラはすべての可能なサブクラスがカバーされているかをチェックします。

kotlin
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の網羅的チェックにより、開発者が画面のすべての可能な表示バリアントを処理していない状態を防ぎます。

sealed classとenum classの比較

enum classとsealed classはしばしば混同されますが、異なる目的と機能を持ちます。

特徴sealed classenum class
インスタンス複数(data class)、単一(object)定数ごとに1つ
プロパティ各サブクラスで異なるすべての定数で同じ
継承可(sealed classから)不可(暗黙的にfinal)
コンストラクタパラメータを持つことができるすべての定数で共通のみ
階層制限付き、sealed固定された定数セット

sealed classとenum classの選択はタスクに依存します。バリアントが追加データを持たない場合はenumを使用します。各バリアントが一意のフィールドを含む場合はsealed classまたはsealed interfaceを使用します。

実用的な使用シナリオ

sealed型は、型安全なモデリングが必要な一連の標準シナリオでKotlinプロジェクトに使用されます。

Jetpack ComposeにおけるUI状態

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 classのすべての直接サブクラスは同じファイルで宣言されなければなりません。sealed interfaceにも同じルールが適用されます。実装は1つのファイルにまとめます。

sealed interfaceは別のファイルに実装を持てますか?

いいえ、単一ファイルのルールはsealed interfaceにも適用されます。すべての実装はsealed interfaceが宣言されたファイルになければなりません。

sealed classとsealed interfaceの違いは何ですか?

sealed interfaceは状態やコンストラクタを持たず、複数の実装を許可します。sealed classはコンストラクタと共有状態を持つことができますが、クラスは1つのsealed classしか継承できません。

sealedクラスはwhen式でどのように役立ちますか?

コンパイラがwhenの完全性をチェックします。すべてのサブクラスが処理されていない場合、コードはコンパイルされません。これにより実行時エラーが排除され、コードの安全性が向上します。

sealed classはコンストラクタを持てますか?

はい、sealed classはコンストラクタを持つことができます(デフォルトでプライベート)。すべてのサブクラスはsuper()を介してこのコンストラクタにパラメータを渡せます。

まとめ

  • sealed class — コンパイル時に既知のサブクラスを持つ制限付き階層
  • sealed interface — 複数実装をサポートする柔軟な代替手段(Kotlin 1.5+)
  • when — コンパイラチェックによる網羅的処理、else不要
  • 1つのファイル — すべてのサブクラスと実装はsealed型と同じファイルになければならない
  • モデリング — UI状態、ネットワーク結果、ナビゲーション、イベントシステム
  • 安全性 — when処理なしで新しいサブクラスを追加するとコンパイルエラー
  • 選択 — デフォルトではsealed interfaceが推奨、共有状態が必要な場合はsealed class

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください