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

Когда используешь sealed class вместо enum?

2.0 Middle🔥 201 комментариев
#Kotlin основы

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

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

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

Sealed Class vs Enum в Kotlin

Это отличный вопрос о выборе правильного инструмента для представления ограниченного набора типов. Хотя на первый взгляд они кажутся похожими, у каждого есть свои сценарии использования.

Что такое Enum?

Enum — это класс, который может иметь только фиксированное количество экземпляров. Каждое значение enum создаётся ровно один раз при загрузке класса.

enum class Status {
    PENDING,
    LOADING,
    SUCCESS,
    ERROR
}

Enum реализует Comparable и Enum интерфейсы, хранит порядок и может использоваться в when без else.

Что такое Sealed Class?

Sealed class — это абстрактный класс, который ограничивает подклассы только теми, что определены в том же файле или пакете. Подклассы могут быть:

  • Другие sealed классы
  • Обычные классы
  • Data классы
  • Objects
sealed class Result<T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val exception: Exception) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

Ключевые различия

АспектEnumSealed Class
Количество экземпляровРовно один на значениеМножество экземпляров подклассов
ДанныеТолько общие для всехКаждый подкласс может иметь свои данные
ПаттернНабор константРазные типы с разными свойствами
ПроизводительностьОптимальнее (singleton)Требует создания объектов
НаследованиеНе наследует другие классыМожет наследовать другие классы

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

1. Фиксированный набор вариантов без дополнительных данных:

enum class Priority {
    LOW,
    MEDIUM,
    HIGH,
    CRITICAL
}

val taskPriority = Priority.HIGH

2. Состояния с одинаковой структурой:

enum class NetworkState {
    CONNECTED,
    DISCONNECTED,
    UNKNOWN
}

3. Когда нужны константы с методами:

enum class Direction(val angle: Float) {
    NORTH(0f),
    EAST(90f),
    SOUTH(180f),
    WEST(270f);

    fun opposite(): Direction = when(this) {
        NORTH -> SOUTH
        SOUTH -> NORTH
        EAST -> WEST
        WEST -> EAST
    }
}

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

1. Разные типы данных для разных состояний:

sealed class ViewState {
    object Loading : ViewState()
    data class Success(val data: List<Item>) : ViewState()
    data class Error(val message: String, val code: Int) : ViewState()
    data class Empty(val reason: String) : ViewState()
}

// Разные данные для разных состояний!

2. Результаты операций (Result/Either паттерн):

sealed class ApiResponse<T> {
    data class Success<T>(val body: T, val headers: Map<String, String>) : ApiResponse<T>()
    data class Error<T>(val code: Int, val message: String, val body: T? = null) : ApiResponse<T>()
    data class NetworkError<T>(val exception: IOException) : ApiResponse<T>()
}

fun parseResponse(response: ApiResponse<User>) {
    when(response) {
        is ApiResponse.Success -> println(response.body)
        is ApiResponse.Error -> println(response.message)
        is ApiResponse.NetworkError -> println(response.exception)
    }
}

3. UI события и действия:

sealed class UserAction {
    data class ClickButton(val buttonId: Int) : UserAction()
    data class EnterText(val text: String) : UserAction()
    object ScrollToTop : UserAction()
    data class SelectItem(val item: Any, val position: Int) : UserAction()
}

4. Иерархия типов:

sealed class Vehicle
data class Car(val doors: Int) : Vehicle()
data class Motorcycle(val hasSidecar: Boolean) : Vehicle()
data class Truck(val loadCapacity: Double) : Vehicle()

Практический пример: выбор инструмента

// ❌ Неправильно — enum для разных данных
enum class Result {
    SUCCESS,   // Но где хранить данные?
    ERROR      // Где хранить сообщение об ошибке?
}

// ✅ Правильно — sealed class
sealed class Result<T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val exception: Exception) : Result<Nothing>()
}

// ✅ Enum когда данные одинаковые
enum class HttpMethod {
    GET,
    POST,
    PUT,
    DELETE
}

Правило большого пальца

  • Enum: много вариантов, одинаковая структура → HTTP методы, приоритеты, статусы
  • Sealed class: разные варианты, разная структура и данные → результаты операций, UI события, иерархии типов

Выбор между ними определяется потребностями в хранении данных и гибкостью архитектуры.