Что такое sealed class?

sealed class в Kotlin — это запечатанный (sealed) абстрактный класс, который позволяет ограничить множество его подклассов, делая его отличным инструментом для безопасной работы с иерархией типов, особенно в when-выражениях.

Такие классы часто применяются при работе с состояниями UI, результатами запросов, ошибками, событиями и навигацией. Они упрощают контроль над логикой, когда объект может быть только одним из нескольких известных вариантов.

📦 Пример

sealed class Result
data class Success(val data: String) : Result()
data class Error(val exception: Throwable) : Result()
object Loading : Result()

🔍 Особенности sealed-классов

1. Ограниченное множество наследников

Все подклассы sealed class должны находиться в одном файле. Это позволяет компилятору знать обо всех возможных вариантах, и делает when-выражения исчерпывающими без else.

fun handle(result: Result) = when (result) {
is Success -> println("Data: ${result.data}")
is Error -> println("Error: ${result.exception.message}")
is Loading -> println("Loading...")
// else не нужен: компилятор знает все варианты
}

2. Абстрактность по умолчанию

sealed class по умолчанию — абстрактный. Нельзя создать её напрямую:

val r = Result() //  ошибка

Можно использовать только её подклассы.

3. Поддержка object, data class, обычных классов

Внутри sealed class можно использовать:

  • object — для уникальных состояний (Loading, Idle);

  • data class — для хранения данных (Success, Error);

  • обычные классы — если нужны более сложные реализации.

4. Может быть вложенным или внешним классом

Sealed-классы можно объявлять как:

sealed class Event {
object Click : Event()
data class Input(val text: String) : Event()
}

или как отдельный класс с наследниками в том же файле:

sealed class Operation
class Add(val a: Int, val b: Int) : Operation()
class Multiply(val a: Int, val b: Int) : Operation()

🧠 Когда использовать sealed class

  • UI-состояния: Loading, Success, Error, Empty.

  • Результаты операций: Success<T>, Failure, InProgress.

  • Навигационные события: NavigateToLogin, ShowToast.

  • Обработка ошибок: HttpError, Timeout, NoInternet.

✅ Преимущества

Преимущество Описание
✅ Безопасность Компилятор знает все возможные подклассы.
--- ---
✅ Упрощение when-блоков Не нужен else, если охвачены все варианты.
--- ---
✅ Лаконичный код Позволяет компактно описывать состояния.
--- ---
✅ Статическая проверка на полноту Помогает не забыть обработать случай.
--- ---

⚠️ Ограничения

  • Все наследники должны быть в одном файле.

  • Не поддерживает многослойную иерархию, как abstract class.

  • Не подходит, если нужно позволить расширение класса в другом модуле.

🔁 Сравнение с другими

Тип Можно расширять в других файлах? Компилятор знает всех наследников?
sealed ❌ Нет ✅ Да
--- --- ---
abstract ✅ Да ❌ Нет
--- --- ---
enum ❌ Нет ✅ Да (но только фиксированные object)
--- --- ---

Итого

sealed class — мощный инструмент в Kotlin для ограниченной и контролируемой иерархии типов. Он делает код безопасным, понятным и удобным для расширения, особенно при моделировании состояний, событий или результатов, которые могут иметь ограниченное число вариантов.