Menu
Coddy logo textTech

Klasy wyliczeniowe

Część sekcji Programowanie obiektowe ścieżki Kotlin w Coddy. Lekcja 33 z 57.

enum class deklaruje typ ze stałym zestawem wartości, czyli jego stałymi. Każda stała jest obiektem typu enum z name i ordinal, czyli swoją pozycją, zaczynającą się od 0. entries wyświetla je w kolejności:

enum class Direction { NORTH, EAST, SOUTH, WEST }

Wewnątrz main:

val d = Direction.EAST
println(d)
println(d.ordinal)
println(Direction.entries)

Wynik:

EAST
1
[NORTH, EAST, SOUTH, WEST]

Stałe typu enum mogą mieć właściwości przekazywane do konstruktora enuma, a sam enum może deklarować metody. Średnik kończy listę stałych przed elementami członkowskimi:

enum class Coin(val cents: Int) {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25);

    fun label() = "${name.lowercase()} ($cents c)"
}

Wewnątrz main:

println(Coin.DIME.label())
println(Coin.entries.sumOf { it.cents })

Wynik:

dime (10 c)
41

Instrukcja when dotycząca wyliczenia, która obejmuje każdą stałą, nie wymaga else, a kompilator zgłasza brakującą stałą. valueOf("SOUTH") wyszukuje stałą po jej dokładnej nazwie i zgłasza wyjątek, jeśli jej nie zna, dlatego dane wejściowe zwykle dopasowuje się za pomocą entries.find:

enum class Direction { NORTH, EAST, SOUTH, WEST }

fun turnRight(d: Direction) = when (d) {
    Direction.NORTH -> Direction.EAST
    Direction.EAST -> Direction.SOUTH
    Direction.SOUTH -> Direction.WEST
    Direction.WEST -> Direction.NORTH
}

fun parse(text: String) = Direction.entries.find { it.name == text.uppercase() }

Wewnątrz main:

println(turnRight(Direction.valueOf("SOUTH")))
println(parse("north"))
println(parse("up"))

Wynik:

WEST
NORTH
null

Stała może mieć własne ciało i nadpisywać w nim metodę. Zadeklarowanie metody abstract w wyliczeniu wymusza jej implementację dla każdej stałej:

enum class Op(val symbol: String) {
    PLUS("+") {
        override fun apply(a: Int, b: Int) = a + b
    },
    TIMES("*") {
        override fun apply(a: Int, b: Int) = a * b
    };

    abstract fun apply(a: Int, b: Int): Int
}

Wewnątrz main:

for (op in Op.entries) println("6 ${op.symbol} 3 = ${op.apply(6, 3)}")

Wynik:

6 + 3 = 9
6 * 3 = 18
challenge icon

Wyzwanie

Łatwy

Uzupełnij enum Size stałymi SMALL (250 ml, cena 300), MEDIUM (350 ml, 380) i LARGE (500 ml, 450), przy czym ceny są podane w centach. label() zwraca medium (350 ml): 3.80, a upsize() zwraca następny większy rozmiar lub ten sam rozmiar dla LARGE. Metoda parse(text) obiektu towarzyszącego znajduje rozmiar na podstawie jego nazwy bez uwzględniania wielkości liter albo na podstawie pierwszej litery (s, M) i w przeciwnym razie zwraca null.

Dostarczony kod odczytuje zamówienia, takie jak medium, L lub up small (napój w większym rozmiarze), i wypisuje etykietę każdego z nich lub unknown size x, a na koniec total: 11.10.

Umieść swój kod w pliku Size.kt. Plik Main.kt zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

fun main() {
    // Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
    val input = generateSequence(::readLine).toList()
    var total = 0
    for (line in input) {
        val upsize = line.startsWith("up ")
        val size = Size.parse(line.removePrefix("up "))
        if (size == null) {
            println("unknown size $line")
            continue
        }
        val chosen = if (upsize) size.upsize() else size
        println(chosen.label())
        total += chosen.price
    }
    println("total: %d.%02d".format(total / 100, total % 100))
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Edytor online Kotlin