← Назад к вопросам

Кто может быть наследником Sealed Class

1.0 Junior🔥 162 комментариев
#Kotlin основы

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Наследники Sealed Class в Kotlin

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

Кто может быть наследником?

Наследниками sealed class могут быть:

  1. Классы (class) — обычные или data классы
  2. Объекты (object) — синглтоны
  3. Sealed классы — вложенные sealed классы для создания многоуровневых иерархий

Основные правила наследования

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

Пример реализации

sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val exception: Throwable) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

sealed class PaymentState {
    object Initial : PaymentState()
    data class Processing(val transactionId: String) : PaymentState()
    data class Completed(val receipt: Receipt) : PaymentState()
    data class Failed(val errorCode: Int) : PaymentState()
    
    // Вложенный sealed class
    sealed class ValidationError : PaymentState() {
        object InvalidCard : ValidationError()
        object InsufficientFunds : ValidationError()
        data class ExpiredCard(val expiryDate: LocalDate) : ValidationError()
    }
}

Ключевые особенности использования

1. Исчерпывающие when-выражения

Самое мощное преимущество sealed классов — компилятор знает все возможные подтипы, что позволяет делать exhaustive when expressions (исчерпывающие выражения when):

fun handleResult(result: Result<String>) {
    when (result) {
        is Result.Success -> println("Данные: ${result.data}")
        is Result.Error -> println("Ошибка: ${result.exception.message}")
        Result.Loading -> println("Загрузка...")
        // Компилятор проверяет, что все случаи обработаны!
    }
}

2. Иерархии состояний

Идеально подходят для моделирования state machines (автоматов состояний):

sealed class DownloadState {
    object Idle : DownloadState()
    data class Progressing(val percent: Int) : DownloadState()
    object Completed : DownloadState()
    data class Failed(val error: String) : DownloadState()
}

3. Паттерн Компаньон

Часто используется в сочетании с companion object для фабричных методов:

sealed class ApiResponse<out T> {
    data class Success<T>(val value: T) : ApiResponse<T>()
    data class Failure(val error: ApiError) : ApiResponse<Nothing>()
    
    companion object {
        fun <T> success(value: T) = Success(value)
        fun failure(error: ApiError) = Failure(error)
    }
}

Ограничения и лучшие практики

  • Нельзя наследовать sealed class вне модуля, где он объявлен
  • Нельзя создавать экземпляры sealed class напрямую
  • Все наследники должны быть явно объявлены — компилятор не допускает неявного наследования
  • Рекомендуется использовать data классы для случаев с данными и object для случаев без состояния

Отличия от enum классов

Хотя sealed classes похожи на enum classes, они более мощные:

// enum — каждый элемент однотипен

enum class Color { RED, GREEN, BLUE }

// sealed class — каждый наследник может иметь разную структуру

sealed class Shape {

    data class Circle(val radius: Double) : Shape()
    data class Rectangle(val width: Double, val height: Double) : Shape()
    data class Triangle(val base: Double, val height: Double) : Shape()
}

### Практическое применение в Android

В Android development sealed classes особенно полезны для:

1. **UI State Management** в MVVM/MVI архитектурах
2. **Event Handling** для обработки событий ViewModel
3. **Navigation** для определения навигационных целей
4. **Network Responses** для типизации ответов API

```kotlin

// Типичный пример в ViewModel

sealed class LoginState {
object Idle : LoginState()
object Loading : LoginState()
data class Success(val user: User) : LoginState()
data class Error(val message: String) : LoginState()

}

Заключение

Sealed classes в Kotlin предоставляют типобезопасный способ моделирования ограниченных иерархий, где компилятор может статически проверять полноту обработки всех случаев. Их наследниками могут быть только явно объявленные в том же модуле классы, data классы, объекты или другие sealed классы, что делает этот механизм предсказуемым и безопасным для рефакторинга и поддержки кодовой базы.

Кто может быть наследником Sealed Class | PrepBro