Что такое 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 — инструмент для типобезопасного моделирования сложных состояний и логики. Они могут дополнять друг друга, но применяются в разных контекстах.