Menu
Coddy logo textTech

Clases enum

Parte de la sección Programación orientada a objetos del Journey de Kotlin de Coddy. Lección 33 de 57.

Una enum class declara un tipo con un conjunto fijo de valores, sus constantes. Cada constante es un objeto del enum con un name y un ordinal, su posición comenzando en 0. entries las enumera en orden:

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

Dentro de main:

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

Salida:

EAST
1
[NORTH, EAST, SOUTH, WEST]

Las constantes de enumeración pueden tener propiedades, que se pasan al constructor de la enumeración, y la enumeración puede declarar métodos. Un punto y coma termina la lista de constantes antes de los miembros:

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

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

Dentro de main:

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

Salida:

dime (10 c)
41

Un when sobre una enumeración que enumera cada constante no necesita else, y el compilador informa de la constante que falta. valueOf("SOUTH") busca una constante por su nombre exacto y produce una excepción si no existe, por lo que normalmente la entrada se compara 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() }

Dentro de main:

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

Salida:

WEST
NORTH
null

Una constante puede tener su propio cuerpo y sobrescribir un método allí. Declarar el método abstract en la enumeración obliga a cada constante 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 de main:

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

Salida:

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

Desafío

Fácil

Completa el enum Size con las constantes SMALL (250 ml, precio 300), MEDIUM (350 ml, 380) y LARGE (500 ml, 450), con los precios en centavos. label() devuelve medium (350 ml): 3.80, y upsize() devuelve el siguiente tamaño más grande, o el mismo tamaño para LARGE. El método companion parse(text) busca un tamaño por su nombre ignorando mayúsculas y minúsculas, o por su primera letra (s, M), y devuelve null en caso contrario.

El código proporcionado lee pedidos como medium, L o up small (la bebida aumentada) e imprime cada etiqueta o unknown size x, y finalmente total: 11.10.

Tu código va en Size.kt. Main.kt contiene el código proporcionado de entrada/salida y no se puede editar.

Pruébalo tú mismo

fun main() {
    // Código de entrada/salida suministrado: déjalo tal como está
    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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Playground de Kotlin