Что такое sealed class?android-77

Что такое sealed class?

Sealed class (запечатанный класс) — это специальный тип класса в Kotlin, который:

  • Представляет ограниченную иерархию классов
  • Все подклассы известны на этапе компиляции
  • Похож на enum, но каждый вариант может иметь собственное состояние и методы
sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val exception: Exception) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

Ключевые особенности

  1. Ограниченное наследование:

    • Подклассы должны быть объявлены в том же файле
    • Начиная с Kotlin 1.5, можно в том же package
  2. Когда использовать:

    • Когда есть фиксированный набор типов результатов/состояний
    • Для реализации паттерна "State" или "Result"
    • Для безопасного моделирования API ответов
  3. Преимущества перед enum:

    • Каждый подкласс может иметь разные свойства
    • Могут быть data class, object или обычные классы
    • Поддержка generics

Практические примеры

1. Моделирование состояния UI

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

// Использование
when (val state = viewModel.uiState) {
    is UiState.Loading -> showProgressBar()
    is UiState.Success -> updateList(state.data)
    is UiState.Error -> showError(state.message)
}

2. Обработка API ответов

sealed class ApiResult<out T> {
    data class Success<T>(val response: T) : ApiResult<T>()
    data class Failure(val error: String) : ApiResult<Nothing>()
}

fun handleResult(result: ApiResult<User>) {
    when (result) {
        is ApiResult.Success -> println("User: ${result.response}")
        is ApiResult.Failure -> println("Error: ${result.error}")
    }
}

3. Иерархия событий

sealed class AnalyticsEvent {
    data class ButtonClicked(val buttonId: String) : AnalyticsEvent()
    data class ScreenViewed(val screenName: String) : AnalyticsEvent()
    object UserLoggedOut : AnalyticsEvent()
}

fun logEvent(event: AnalyticsEvent) = when (event) {
    is ButtonClicked -> track("button_${event.buttonId}_click")
    is ScreenViewed -> track("screen_${event.screenName}_view")
    UserLoggedOut -> track("user_logout")
}

Отличия от похожих концепций

Характеристика Sealed class Enum class Abstract class
ЭкземплярыМножество разных типовФиксированные константыНельзя создать экземпляр
СостояниеМожет иметь поляОдно состояниеМожет иметь поля
НаследованиеТолько внутри файлаНет наследованияЛюбые подклассы
Когда использоватьОграниченная иерархияФиксированные значенияОбщая реализация

Резюмируем

  1. Sealed class — мощный инструмент для:

    • Моделирования ограниченных иерархий
    • Безопасной обработки состояний (exhaustive when)
    • Создания читаемых и поддерживаемых API
  2. Основные преимущества:

    • Полная проверка на этапе компиляции
    • Поддержка разных типов данных в подклассах
    • Идеально подходит для State Management
  3. Рекомендации:

    • Используйте для UI состояний и результатов операций
    • Комбинируйте с data class для хранения информации
    • Применяйте object для singleton-состояний

Sealed classes делают код более выразительным и безопасным, уменьшая вероятность ошибок времени выполнения.