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 class(シールドクラス)

Posted at

はじめに

Kotlin の sealed class(シールドクラス)は、継承範囲を制限できる特殊な抽象クラスです。
主に「状態」や「結果」などを安全に表現するために使われます。
enum class より柔軟で、abstract class より安全に状態を管理できるのが特徴です。


sealed class とは?

sealed class は「同じファイル内でのみ継承可能」なクラスです。
これにより、想定外のサブクラス定義を防ぎ、型の網羅性を保証できます。

基本構文

sealed class Result

class Success(val data: String) : Result()
class Error(val message: String) : Result()
object Loading : Result()
  • sealed class 自体は abstract(抽象クラス)
  • サブクラスは 同じ Kotlin ファイル内 に定義する必要あり
  • これにより、安全で予測可能な継承ツリーを構築できる

when 式との組み合わせが強力!

sealed class の最大のメリットは、when 式で 網羅性チェック ができることです。

fun handle(result: Result) = when (result) {
    is Success -> println("成功: ${result.data}")
    is Error -> println("エラー: ${result.message}")
    Loading -> println("読み込み中…")
    // else が不要! → コンパイラが全ケースを認識している
}

sealed class のすべての派生クラスを コンパイル時に把握できる ため、
else 分岐なしで安全な when 式が書けます。


ジェネリクスと組み合わせた実用例

API 呼び出し結果を表す「Result 型」を定義してみましょう。

sealed class Result<out T> {
    data class Success<out T>(val data: T) : Result<T>()
    data class Error(val exception: Throwable) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

使い方例

fun loadUser(): Result<String> {
    return try {
        val user = "Anna"
        Result.Success(user)
    } catch (e: Exception) {
        Result.Error(e)
    }
}

fun showResult(result: Result<String>) = when (result) {
    is Result.Success -> println("ユーザー名: ${result.data}")
    is Result.Error -> println("エラー発生: ${result.exception.message}")
    Result.Loading -> println("ロード中…")
}

Success / Error / Loading の3つの状態を安全に扱える構造。


sealed class と enum class の違い

比較項目 sealed class enum class
定義の柔軟性 任意のクラス構造が定義できる 固定値のみ
データ保持 可能(プロパティあり) 不可(定数のみ)
継承 可(同ファイル内のみ) 不可
when 式の網羅性 あり あり
主な用途 状態表現、結果モデリング 定数グループ化

sealed interface との違い

Kotlin 1.5 以降では、sealed interface も導入されました。
クラスに縛られず、より柔軟に状態やイベントを表現できます。

sealed interface UiState

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

sealed interface は「複数の型にまたがる状態管理」に便利です。


実践例:UI 状態の管理(MVVM / MVI)

例えば Android の ViewModel で使うとこうなります。

sealed class UiState {
    object Loading : UiState()
    data class Success(val items: List<String>) : UiState()
    data class Error(val message: String) : UiState()
}

class UserViewModel : ViewModel() {
    private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
    val uiState = _uiState.asStateFlow()

    fun loadUsers() {
        viewModelScope.launch {
            try {
                val users = fetchUsers()
                _uiState.value = UiState.Success(users)
            } catch (e: Exception) {
                _uiState.value = UiState.Error("読み込みに失敗しました")
            }
        }
    }
}

これで UI 層は安全に状態を観察できます。

viewModel.uiState.collect { state ->
    when (state) {
        is UiState.Loading -> showLoading()
        is UiState.Success -> showList(state.items)
        is UiState.Error -> showError(state.message)
    }
}

まとめ

ポイント 説明
継承範囲を制限 同一ファイル内のみ継承可
型安全 when 式で網羅性チェック
柔軟 enum より柔軟に状態・結果を表現できる
実用例 API 結果、UI 状態、イベント管理など
拡張機能 Kotlin 1.5以降で sealed interface にも対応

sealed class は Kotlin の中でも特に「状態管理」や「エラー処理」を安全・明確に表現できる強力な仕組みです。
enum より柔軟に、abstract class より安全に。
アプリの状態設計をより堅牢にするために、ぜひ活用してみてください。

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?