Освой Kotlin играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Перечислительный класс (enum)

Тот редкий случай, когда в Kotlin ключевое слово enum используется до ключевого слова class. В Kotlin enum относится к разряду мягких ключевых слов (soft keyword), которое является ключевым только перед ключевым словом class. В других случаях вы можете использовать его свободно как простое имя переменной.


// Документы кота: усы, лапы, хвост
enum class CatDocument {
    VIBRISSAE, PAWS, TAIL
}

val paws = CatDocument.PAWS
println(paws)

// Дни недели
enum class DayOfWeek {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

Получить все значения перечисления. Мы можем получить как имя константы в перечислении, так и его значение с помощью встроенного свойства name. Порядковый номер можно получить через ordinal.


// получим все части документа
for (documentPart in CatDocument.values()){
    println("name: ${documentPart.name}, ordinal: ${documentPart.ordinal}")
}

/*
name: VIBRISSAE, ordinal: 0
name: PAWS, ordinal: 1
name: TAIL, ordinal: 2
*/

Можем задать элементам перечисления значения.


// Enum with values
enum class Capital(val capital: String) {
    Russia("Moscow"),
    Ukraine("Kyiv"),
    Belarus("Minsk")
}

val builder = StringBuilder()
builder.append("\nRussia = ${Capital.Russia.capital}")
builder.append("\nUkraine = ${Capital.Ukraine.capital}")
builder.append("\nBelarus = ${Capital.Belarus.capital}")

textView.text = builder.toString()

/*
Russia = Moscow
Ukraine = Kyiv
Belarus = Minsk
*/

// Пример с днями недли
enum class DayOfWeek(val number: Int) {
    MONDAY(1),
    TUESDAY(2),
    WEDNESDAY(3),
    THURSDAY(4),
    FRIDAY(5),
    SATURDAY(6),
    SUNDAY(7)
}
 
fun getDayNumber(day: DayOfWeek): Int {
    return day.number
}

println(getDayNumber(DayOfWeek.SATURDAY)) // 6

Можно задать несколько значений.


// Enum with multiple values
enum class Country(val capital: String, val currency: String) {
    Russia("Moscow", "Ruble"),
    Ukraine("Kyiv", "Hryvnia"),
    Belarus("Minks", "Belarusian ruble")
}

val builder = StringBuilder()
builder.append("\n\nRussia = ${Country.Russia.capital}, ${Country.Russia.currency}")
builder.append("\nUkraine = ${Country.Ukraine.capital}, ${Country.Ukraine.currency}")
builder.append("\nBelarus = ${Country.Belarus.capital}, ${Country.Belarus.currency}")

textView.text = builder.toString()

/*
Russia = Moscow, Ruble
и т.д.
*/

Можно задать значение по умолчанию.


enum class Cat(val catName: String, val gender: String? = "Кот") {
    Vaska("Васька"),
    Murzik("Мурзик"),
    Murka("Мурка", "Кошка") // задаём собственное значение
}

val builder = StringBuilder()
builder.append("\n${Cat.Murzik.catName}, ${Cat.Murzik.gender}")
builder.append("\n${Cat.Vaska.catName}, ${Cat.Vaska.gender}")
builder.append("\n${Cat.Murka.catName}, ${Cat.Murka.gender}")

textView.text = builder.toString()

По умолчанию у всех котиков будет слово Кот и его указывать не нужно, а у Мурки мы задаём своё уникальное значение (Кошка).

В отличие от Java вы можете в перечислении задавать свойства и определять функции. Учебный пример от разработчиков языка.


enum class Color(
    val r: Int, val g: Int, val b: Int
) {
    RED(255, 0, 0), ORANGE(255, 165, 0),
    YELLOW(255, 255, 0), GREEN(0, 255, 0), BLUE(0, 0, 255),
    INDIGO(75, 0, 130), VIOLET(238, 130, 238);

    fun rgb() = (r * 256 + g) * 256 + b
}

fun main(args: Array<String>) {
    println(Color.BLUE.rgb())
}

В примере мы определили три отдельных переменных r, g, b, затем задали список перечислений и функцию для вычисления значения цвета. Обратите внимание, что в одном месте используется обязательная точка с запятой перед вызовом функции.

Теперь пример с днями недели. Внутри перечисления создадим функцию,определяющую выходной день.


enum class DayOfWeek(val number: Int) {
     MONDAY(1),
     TUESDAY(2),
     WEDNESDAY(3),
     THURSDAY(4),
     FRIDAY(5),
     SATURDAY(6),
     SUNDAY(7);

    fun isWeekend(): Boolean {
        return this == SATURDAY || this == SUNDAY
    }
}

fun printDayType(day: DayOfWeek) {
    if (day.isWeekend()) {
        println("$day is a weekend day.")
    } else {
        println("$day is a weekday.")
    }
}

println(printDayType(DayOfWeek.SATURDAY))

В выражениях when должны учитываться все условия, то есть они должны быть исчерпывающими. Поскольку перечислительные классы ограничивают возможные значения, компилятор Kotlin может использовать эту информацию, чтобы понимать, когда все условия были действительно учтены. И поэтому можно не использовать ветвь else (при этом нельзя пропускать какие-то варианты, все условия нужно использовать либо добавлять else).

Реклама