Sealed конструкции — это мощный инструмент Kotlin
для создания ограниченных иерархий типов, которые известны на этапе компиляции.
Они сочетают в себе преимущества enum
и абстрактных классов, но с большей гибкостью.
- Запечатанность - Все подклассы должны быть объявлены в том же файле, что и
sealed
класс (доKotlin 1.5
) или в одном пакете (Kotlin 1.5+
). - Использование - Идеально для представления ограниченного набора вариантов, например, состояний
UI
или результатов операций.
Синтаксис:
sealed class Result {
data class Success(val data: String) : Result()
data class Error(val message: String) : Result()
object Loading : Result()
}
Пример использования:
fun handleResult(result: Result) = when (result) {
is Result.Success -> println("Data: ${result.data}")
is Result.Error -> println("Error: ${result.message}")
Result.Loading -> println("Loading...")
}
// Компилятор проверяет, что все случаи обработаны!
- Каждый подкласс может иметь разные свойства и методы.
- Поддерживают наследование и полиморфизм.
- Аналогичны
sealed
классам, но для интерфейсов. - Полезны, когда нужно реализовать несколько независимых иерархий.
Пример:
/**
* Запечатанный интерфейс, представляющий модель пагинации.
* Используется для отображения данных, ошибок и состояния загрузки в RecyclerView.
*
* @property T Тип данных, которые загружаются.
*/
sealed interface PagingModel<out T> {
/**
* Модель данных, содержащая загруженные данные.
*
* @property value Загруженные данные.
*/
data class Data<T>(val value: T) : PagingModel<T>
/**
* Модель ошибки, содержащая информацию об ошибке.
*
* @property reason Исключение, вызвавшее ошибку.
*/
data class Error(val reason: Throwable) : PagingModel<Nothing>
/**
* Модель состояния загрузки.
*/
data object Loading : PagingModel<Nothing>
/**
* Модель разделителя даты.
*
* @property date Дата, которая будет отображаться в разделителе.
*/
data class DateSeparator(val date: String) : PagingModel<Nothing>
}
Пример использования:
override fun getItemViewType(position: Int): Int =
when (getItem(position)) {
is PagingModel.Data -> TYPE_POST
is PagingModel.Error -> TYPE_ERROR
is PagingModel.Loading -> TYPE_LOADING
is PagingModel.DateSeparator -> TYPE_DATE_SEPARATOR
}
- Для представления синглтонов в sealed иерархии (например, состояния загрузки).
Пример:
sealed class UiState {
data class Content(val text: String) : UiState()
object Empty : UiState() // Синглтон
}
Sealed
классы раскрывают всю мощь Kotlin
в when
-выражениях:
fun process(result: Result) = when (result) {
is Result.Success -> { /* работаем с result.data */ }
is Result.Error -> { /* обрабатываем result.message */ }
Result.Loading -> { /* показываем лоадер */ }
}
override fun getItemViewType(position: Int): Int =
when (getItem(position)) {
is PagingModel.Data -> TYPE_POST
is PagingModel.Error -> TYPE_ERROR
is PagingModel.Loading -> TYPE_LOADING
is PagingModel.DateSeparator -> TYPE_DATE_SEPARATOR
}
Важно: Если when
используется как выражение (возвращает значение), компилятор требует обработки всех вариантов.
- Эффективность -
Sealed
классы компилируются вfinal
-классы с приватным конструктором. - Безопасность - Компилятор гарантирует, что все подклассы известны заранее, что исключает ошибки в
when
.
- До
Kotlin 1.5
: Подклассы должны быть вложены вsealed
класс. - Нельзя наследовать
sealed
класс/интерфейс извне файла/пакета.
UI
состояния (загрузка, ошибка, контент).- Результаты операций (успех/ошибка).
- Команды в
MVI
-архитектуре. - Альтернатива
enum
, когда нужны разные данные для каждого варианта.
Sealed
конструкции делают код типобезопасным и легко расширяемым — идеально для современных Android
-приложений!
Sealed class (изолированный класс) — это класс, который является абстрактным и используется в Kotlin
для ограничения классов, которые могут наследоваться от него.
Основная идея заключается в том, что sealed class
позволяет определить ограниченный и известный заранее набор подклассов, которые могут быть использованы.
- Конструктор изолированного класса всегда приватен, и это нельзя изменить.
- У
sealed
класса могут быть наследники, но все они должны находиться в одном пакете с изолированным классом. Изолированный класс "открыт" для наследования по умолчанию, указывать словоopen
не требуется. - Наследники
sealed
класса могут быть классами любого типа:data class
, объектом, обычным классом, другимsealed
классом. Классы, которые расширяют наследниковsealed
класса могут находиться где угодно. - Изолированные классы абстрактны и могут содержать в себе абстрактные компоненты.
- Изолированные классы нельзя инициализировать.
- При использовании
when
, все подклассы, которые не были проверены в конструкции, будут подсвеченыIDE
. - Не объявляется с ключевым словом
inner
.