0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Kotlin】Kotlin の sealed interface(シールドインターフェース)

Posted at

はじめに

sealed interface は Kotlin 1.5 以降で登場した新しい概念で、
sealed class の「継承制限」機能を インターフェースにも適用できる ようにしたものです。

これにより、「状態・イベント・結果」などの型階層を、
より柔軟かつ安全に表現できるようになりました。


sealed interface とは?

sealed interface は「同一モジュール内でのみ実装できるインターフェース」です。
sealed class と似ていますが、いくつか重要な違いがあります。

基本構文

sealed interface UiState

data class Success(val data: String) : UiState
object Loading : UiState
object Error : UiState

特徴まとめ

  • 同一モジュール内でのみ実装可能(sealed class は同一ファイル内)
  • 継承ツリーを限定的かつ柔軟に定義できる
  • when 式で網羅性チェックが可能(else 不要)

sealed class との違い

比較項目 sealed class sealed interface
継承できる範囲 同一ファイル内 同一モジュール内
実装可能数 1クラスのみ(単一継承) 複数のインターフェースを同時実装可
状態保持 可能(プロパティを持てる) 不可(状態は実装クラス側で保持)
主な用途 結果や状態を直接表すモデル 複数の状態やイベントを表す抽象プロトコル

なぜ sealed interface が必要なの?

sealed class は単一継承しかできないため、
「複数の概念に属する状態」を表現するのが難しい場合があります。

一方 sealed interface は、
複数の sealed interface を同時に実装できるため、柔軟な状態表現が可能です。


実践例:UI 状態の階層化

例:ロード状態を表す sealed interface

sealed interface UiState

sealed interface LoadingState : UiState
sealed interface ErrorState : UiState
sealed interface SuccessState : UiState

data class Loaded(val data: String) : SuccessState
object Loading : LoadingState
data class Error(val message: String) : ErrorState

各状態が独立していながら、共通して UiState を継承しているため
UI 層で when (state) を使って網羅的に扱えます。


when 式の網羅性チェック

fun render(state: UiState) = when (state) {
    is Loaded -> println("データ: ${state.data}")
    is Loading -> println("読み込み中…")
    is Error -> println("エラー: ${state.message}")
    // else 不要!コンパイラが全ケースを認識
}

→ sealed interface でも when の網羅性チェックが効きます。
「型安全な状態管理」 を行うには最適です。


MVI・Reduxパターンでの利用例

sealed interfaceMVI (Model–View–Intent) のような
イベント駆動アーキテクチャで特に威力を発揮します。

sealed interface UiEvent {
    data object OnClick : UiEvent
    data class OnTextChanged(val text: String) : UiEvent
    data object OnRetry : UiEvent
}

sealed interface UiState {
    object Loading : UiState
    data class Success(val data: String) : UiState
    data class Error(val message: String) : UiState
}

ViewModel でイベントを受け取り、状態を更新する流れがスッキリ書けます。

fun onEvent(event: UiEvent) {
    when (event) {
        UiEvent.OnClick -> loadData()
        is UiEvent.OnTextChanged -> updateText(event.text)
        UiEvent.OnRetry -> retry()
    }
}

Intent(入力)と State(出力) の両方に sealed interface が使えます。


sealed class と sealed interface の使い分け

状況 推奨構文 理由
状態にデータを持たせたい sealed class プロパティを直接持てる
状態をプロトコル的に定義したい sealed interface 複数の型が共通契約を実装できる
状態 + イベントを統一管理したい sealed interface 柔軟な構成に向く
ファイル単位で閉じたい sealed class 継承範囲を完全制限

まとめ

  • sealed interface は Kotlin 1.5 以降で登場
  • 同一モジュール内でのみ実装可能
  • 複数の sealed interface を多重実装できる
  • when 式の網羅性チェックに対応
  • MVI / Redux パターンで特に有効

sealed interfacesealed class の柔軟版です。
状態やイベントを安全かつ拡張性のある形で表現するための必須ツール になりつつあります。

特に Android の MVICompose の状態管理においては、
「UI State」「UI Event」「Action」などを sealed interface で定義するのが主流になっています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?