Skip to content

Latest commit

 

History

History
193 lines (138 loc) · 8.45 KB

README.md

File metadata and controls

193 lines (138 loc) · 8.45 KB

Sealed классы и интерфейсы в Kotlin


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


Sealed классы

Основные свойства

  • Запечатанность - Все подклассы должны быть объявлены в том же файле, что и 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...")
}
// Компилятор проверяет, что все случаи обработаны!

Преимущества перед enum

  • Каждый подкласс может иметь разные свойства и методы.
  • Поддерживают наследование и полиморфизм.

Sealed интерфейсы (Kotlin 1.5+)

Особенности

  • Аналогичны 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 иерархии (например, состояния загрузки).

Пример:

sealed class UiState {
    data class Content(val text: String) : UiState()
    object Empty : UiState()  // Синглтон
}

Pattern Matching с when

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 класс/интерфейс извне файла/пакета.

Когда использовать Sealed?

  • UI состояния (загрузка, ошибка, контент).
  • Результаты операций (успех/ошибка).
  • Команды в MVI-архитектуре.
  • Альтернатива enum, когда нужны разные данные для каждого варианта.

Sealed конструкции делают код типобезопасным и легко расширяемым — идеально для современных Android-приложений!


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

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

  • Конструктор изолированного класса всегда приватен, и это нельзя изменить.
  • У sealed класса могут быть наследники, но все они должны находиться в одном пакете с изолированным классом. Изолированный класс "открыт" для наследования по умолчанию, указывать слово open не требуется.
  • Наследники sealed класса могут быть классами любого типа: data class, объектом, обычным классом, другим sealed классом. Классы, которые расширяют наследников sealed класса могут находиться где угодно.
  • Изолированные классы абстрактны и могут содержать в себе абстрактные компоненты.
  • Изолированные классы нельзя инициализировать.
  • При использовании when, все подклассы, которые не были проверены в конструкции, будут подсвечены IDE.
  • Не объявляется с ключевым словом inner.