Menu
Coddy logo textTech

Classi enum

Fa parte della sezione Programmazione orientata agli oggetti del percorso Kotlin di Coddy. Lezione 33 di 57.

Una enum class dichiara un tipo con un insieme fisso di valori, le sue costanti. Ogni costante è un oggetto dell'enum con un name e un ordinal, la sua posizione a partire da 0. entries le elenca in ordine:

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

All'interno di main:

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

Output:

EAST
1
[NORTH, EAST, SOUTH, WEST]

Le costanti enum possono avere proprietà, passate al costruttore dell'enum, e l'enum può dichiarare metodi. Un punto e virgola conclude l'elenco delle costanti prima dei membri:

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

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

All'interno di main:

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

Output:

dime (10 c)
41

Un when su un enum che elenca ogni costante non ha bisogno di else, e il compilatore segnala una costante mancante. valueOf("SOUTH") trova una costante tramite il suo nome esatto e genera un'eccezione se non è nota, quindi di solito l'input viene cercato con 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() }

All'interno di main:

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

Output:

WEST
NORTH
null

Una costante può avere un proprio corpo e sovrascrivere un metodo al suo interno. Dichiarare il metodo abstract nell'enum obbliga ogni costante a implementarlo:

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
}

Dentro main:

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

Output:

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

Sfida

Facile

Completa l'enum Size con le costanti SMALL (250 ml, prezzo 300), MEDIUM (350 ml, 380) e LARGE (500 ml, 450), con i prezzi espressi in centesimi. label() restituisce medium (350 ml): 3.80 e upsize() restituisce la taglia immediatamente più grande, oppure la stessa taglia per LARGE. Il companion parse(text) trova una taglia in base al nome, ignorando le maiuscole e le minuscole, oppure in base alla prima lettera (s, M), e restituisce null in caso contrario.

Il codice fornito legge ordini come medium, L o up small (la bevanda con taglia aumentata) e stampa ogni etichetta oppure unknown size x, e infine total: 11.10.

Il tuo codice va inserito in Size.kt. Main.kt contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

fun main() {
    // Codice di input/output fornito: lascialo così com'è
    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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Playground Kotlin