Классы перечисления
#
Васильев Андрей Михайлович
Версии презентации
Описание классов-перечислений
#
Наиболее базовый пример использования классов-перечислений — это реализация
типобезопасных перечислений
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() и enumValueOf():
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 стало ошибкой компиляции.