Классы перечисления #
Васильев Андрей Михайлович
Версии презентации
Описание классов-перечислений #
Наиболее базовый пример использования классов-перечислений — это реализация типобезопасных перечислений
enum class Direction {
NORTH, SOUTH, WEST, EAST
;
}- Каждая константа перечисления является объектом
- При объявлении константы разделяются запятыми
- Перечисление констант завершается точкой с запятой
- После точки с запятой идёт описание функций-членов и объектов-компаньонов
Данные констант #
Так как константы являются экземплярами enum-класса, они могут иметь собственные свойства, значения которых задаются при объявлении константы
enum class Color(val rgb: Int, val description: String) {
RED(0xFF0000, "Красный"),
GREEN(0x00FF00, "Зелёный"),
BLUE(0x0000FF, "Синий"),
;
}К полям объекта можно обращаться как к обычным полям
val color = Color.GREEN
println(color.description)Стандартные данные констант #
Каждая enum-константа имеет поля, в которых содержатся её имя и порядковый номер в объявлении enum-класса
Вы не можете переопределить данные поля
val name: String
val ordinal: IntТакже enum-константы реализуют интерфейс Comparable. Порядок сортировки
соответствует порядку объявления
println(Direction.NORTH.name) // prints NORTH
println(Direction.NORTH.ordinal) // prints 0Работа с enum-константами #
Enum-классы в Kotlin имеют синтетические методы для вывода списка объявленных enum-констант и для получения enum-константы по её имени
enum class RGB { RED, GREEN, BLUE }
RGB.valueOf(value: String): RGB
RGB.entries: EnumEntries<RGB>Метод valueOf() выбрасывает исключение IllegalArgumentException, если
указанное имя не соответствует ни одной enum-константе, объявленной в классе
fun main() {
for (color in RGB.entries) println(color.toString())
println("The first color is: ${RGB.valueOf("RED")}")
}Свойство entries появилось в Kotlin 1.8.20 и стало стабильным в 1.9.0;
в более ранних версиях использовался метод values(), который возвращал
новый массив из констант
Обобщённый доступ к константам #
К константам в enum-классе можно получить доступ универсальным способом,
используя функции enumEntries
inline fun <reified T : Enum<T>> printAllValues() {
print(enumEntries<T>().joinToString { it.name })
}
printAllValues<RGB>() // выведет RED, GREEN, BLUEДо появления enumEntries<T>() (стабилен с 1.9.0) использовался метод
enumValues<T>(), который также возвращает новый массив из констант
Условное выражение when #
when определяет условное выражение с несколькими «ветвями». Оно похоже на
оператор switch, присутствующий в C-подобных языках.
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // обратите внимание на блок
print("x не равен ни 1, ни 2")
}
}when последовательно сравнивает свой аргумент со всеми указанными значениями,
пока не выполнится какое-либо из условий ветвей.
Полнота вычислений #
Если when используется как выражение, то ветка else является обязательной, за
исключением случаев, в которых компилятор может убедиться, что ветки покрывают
все возможные значения
Так происходит, например с записями классов-перечислений
enum class Bit {
ZERO, ONE
}
val numericValue = when (getRandomBit()) {
Bit.ZERO -> 0
Bit.ONE -> 1
// 'else' не требуется, потому что все случаи учтены
}В операторах when ветка else является обязательной в следующих условиях:
- аргумент
whenимеет типBoolean,enum,sealedили ихnullable-аналоги - ветки
whenне охватывают все возможные случаи для этого аргумента
Требование полноты веток для оператора when с аргументом типа Boolean,
enum или sealed появилось как предупреждение в Kotlin 1.6.0 и в Kotlin
1.7.0 стало ошибкой компиляции.