Что такое enum class и чем она отличается от sealed?

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

Что такое enum class

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

Пример:

enum class Direction {
NORTH, SOUTH, EAST, WEST
}

Каждое значение Direction.NORTH, Direction.SOUTH и т. д. — это объект, и при этом все они — синглтоны.

Возможности enum class

  • Можно задавать свойства и методы:
enum class Status(val code: Int) {
SUCCESS(200),
NOT_FOUND(404),
SERVER_ERROR(500);
fun isSuccess(): Boolean = this == SUCCESS
}
  • Enum автоматически предоставляет:

    • name: имя константы как строки.

    • ordinal: индекс константы (начинается с 0).

    • values(): массив всех значений.

    • valueOf(String): получение enum по имени.

Что такое sealed class

sealed class — это абстрактный класс, ограничивающий количество своих подклассов. Все наследники должны быть определены в одном и том же файле, что позволяет компилятору знать все возможные варианты и использовать when без else.

Пример:

sealed class Response
data class Success(val data: String) : Response()
data class Failure(val error: Throwable) : Response()
object Loading : Response()

Отличия enum class vs sealed class

Особенность enum class sealed class
Поддержка различных полей Один набор полей и методов для всех значений Каждый подкласс может иметь свои уникальные свойства
--- --- ---
Поддержка наследования Нет: enum не может наследовать другие классы/интерфейсы напрямую Да: можно создавать иерархии с уникальной логикой
--- --- ---
Расширяемость Не расширяется — значения жёстко зафиксированы Можно добавлять новых наследников (в рамках одного файла)
--- --- ---
Сопровождение логики Методы можно задавать общие или переопределять в каждом значении Можно полностью изолировать бизнес-логику в разных классах
--- --- ---
Использование в when без else Да Да
--- --- ---
Генерация кода Компилятор создаёт дополнительный код (values(), ordinal) Нет автоматических методов, нужно писать вручную
--- --- ---
Семантика Фиксированные элементы без изменяемых параметров Более выразительные типы с состоянием и параметрами
--- --- ---
Примеры Статусы, флаги, режимы, направления Состояния UI, результаты вычислений, команды и события
--- --- ---

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

  • Когда набор значений фиксирован и простой.

  • Когда все элементы однородны.

  • Когда удобно использовать ordinal, values() и valueOf.

  • Примеры: уровни логирования, роли пользователя, HTTP-статусы.

Пример:

enum class Priority(val level: Int) {
LOW(1),
MEDIUM(2),
HIGH(3)
}

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

  • Когда значения имеют разную структуру.

  • Когда у каждого значения своя логика или данные.

  • Когда нужна гибкость и контроль.

  • Когда необходимо расширение (в рамках файла).

  • Примеры: UI-состояния, результаты операций, выражения языка, ошибки.

Пример:

sealed class UiState
object Loading : UiState()
data class Success(val data: List<String>) : UiState()
data class Error(val message: String) : UiState()

Enum с полиморфным поведением (ограниченно)

Enum может содержать абстрактные методы и реализовывать их отдельно для каждой константы:

enum class Animal {
DOG {
override fun speak() = "Bark"
},
CAT {
override fun speak() = "Meow"
};
abstract fun speak(): String
}

Однако здесь всё равно нельзя задать разные свойства для DOG и CAT — только методы. Это делает enum менее гибким, чем sealed class.

Связка sealed class и enum class

Иногда удобно использовать enum class внутри sealed class:

sealed class LogLevel {
enum class Level { DEBUG, INFO, WARN, ERROR }
data class Message(val level: Level, val text: String) : LogLevel()
}

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