Классы перечисления
#
Васильев Андрей Михайлович, 2024
Версии презентации
Описание классов-перечислений
#
Наиболее базовый пример использования классов-перечислений — это реализация
типобезопасных перечислений
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(RGB.RED.name) // prints RED
println(RGB.RED.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")}")
}
В Kotlin до 1.8 вместо entries предоставлялся метод values(), который
возвращал новый массив из констант
Обобщённый доступ к константам
#
К константам в enum-классе можно получить доступ универсальным способом,
используя функции enumEntries() и enumValueOf():
inline fun <reified T : Enum<T>> printAllValues() {
print(enumEntries<T>().joinToString { it.name })
}
printAllValues<RGB>() // выведет RED, GREEN, BLUE
В Kotlin до 1.8 вместо enumEntries<T>() предоставлялся метод
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 не охватывают все возможные случаи для этого объекта