ПрограммированиеKotlin разработчик

Что такое "sealed class" в Kotlin и как они упрощают обработку состояний? Как sealed class связаны с when-выражением и почему это важно для type-safety? Приведите пример использования.

Проходите собеседования с ИИ помощником Hintsage

Ответ

sealed class в Kotlin — это абстрактный класс, ограничивающий иерархию наследников: все подтипы должны быть объявлены в одном файле. Это удобно для иерархий, где набор вариантов фиксирован (например, для описания состояний, событий или ошибок):

sealed class Result { object Success : Result() data class Error(val message: String) : Result() object Loading : Result() } fun handle(result: Result) = when (result) { is Result.Success -> print("Success!") is Result.Error -> println("Error: ${result.message}") is Result.Loading -> println("Loading...") }

Связь с when: Если мы используем все подтипы sealed class в when-выражении, то компилятор проверяет exhaustiveness (исчерпывающий разбор вариантов). Это гарантирует, что при добавлении нового состояния разработчик получит ошибку компиляции, если не обработает новый вариант.

Зачем это нужно:

  • Упрощает поддержку type-safety.
  • Независимость от runtime-проверок, обработка происходит на этапе компиляции.
  • Заставляет явно рассмотреть все варианты иерархии.

Вопрос с подвохом

"Можно ли располагать наследников sealed class в разных файлах или пакетах? Как это влияет на type-safety?"

Ответ: Нет, все прямые наследники sealed class должны быть определены в одном файле. Это контроль компилятора для гарантий type-safety. Если наследников разместить в других файлах пакета, компилятор выдаст ошибку.


Примеры реальных ошибок из-за незнания тонкостей темы


История

При проектировании бизнес-логики платежей добавляли варианты результатов операции, забыв обновить when-выражение. Но благодаря sealed class, компилятор подсветил неучтённые случаи. В другом проекте на Java этот сценарий привёл бы к попаданию неинициализированного статуса в продукт.


История

В проекте после миграции части данных sealed class на обычные open class перестали работать exhaustive when-проверки — новые статусы начали "теряться" в логике обработки, что вызывало некорректное поведение интерфейса.


История

В e-commerce системе была попытка оптимизировать архитектуру через вынесение наследников sealed class в отдельные файлы (каждый — в свой модуль для переиспользования). Это сломало компиляцию и стало причиной экстренного рефакторинга перед релизом.