Что такое sealed class

Ответ

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

sealed class Result {
    data class Success(val data: String) : Result()
    data class Error(val message: String) : Result()
    object Loading : Result()
}

Особенности:

  • Все наследники известны на этапе компиляции.
  • Автоматически final — нельзя наследовать вне sealed class.
  • Идеально подходит для when с гарантией покрытия всех случаев (без else).
fun handleResult(result: Result) = when(result) {
    is Result.Success -> println(result.data)
    is Result.Error -> println(result.message)
    Result.Loading -> println("Loading...")
}

Ответ 18+ 🔞

А, ну это sealed class! Слушай, это вообще одна из самых офигенных штук в Котлине, я тебе щас объясню, почему.

Представь себе, что ты пишешь какой-нибудь результат операции. Раньше, в старые добрые времена, мы бы тупо сделали обычный класс Result и нагородили кучу наследников где попало. А потом в when приходилось лепить else на всякий случай, а вдруг какой-то новый тип вылезет, который ты не предусмотрел? Доверия ебать ноль к такой архитектуре.

Так вот, sealed class — это как раз про то, чтобы поставить всех этих наследников под контроль. Это как хуй с горы — все видят, откуда он взялся и куда катится. Ты объявляешь запечатанный класс, и все его дети обязаны сидеть с ним в одном файле. Никаких сюрпризов! Все возможные варианты известны компилятору сразу.

Смотри на примере:

sealed class Result {
    data class Success(val data: String) : Result()
    data class Error(val message: String) : Result()
    object Loading : Result()
}

Вот, видишь? Success, Error и Loading — это всё, что есть. Больше ничего придумать и добавить где-то в другом углу проекта нельзя. Компилятор это знает.

И вот тут начинается магия. Когда ты пишешь when по такому классу, компилятор становится твоим лучшим другом. Он проверяет, все ли ветки ты покрыл. Если ты забудешь про Loading, он тебе скажет: «Э, сабака сука, э бошка думай! Куда Loading дел?». И не даст скомпилироваться, пока не добавишь обработку для всех случаев.

fun handleResult(result: Result) = when(result) {
    is Result.Success -> println(result.data)
    is Result.Error -> println(result.message)
    Result.Loading -> println("Loading...")
    // else не нужен, ёпта! Компилятор и так знает, что других вариантов нет.
}

Полная безопасность, никаких неожиданностей в рантайме. Это овердохуища удобно для state management'а в UI, для обработки результатов сетевых запросов — да для чего угодно, где есть чёткий, ограниченный набор состояний.

Короче, sealed class — это не просто синтаксический сахар. Это мощный инструмент для создания надёжного и предсказуемого кода. Ядрёна вошь, как же без него раньше жили-то?