Curso Kotlin | #11. Condicional When

En la clase anterior estudiamos las estructuras condicionales con If y usamos el ejemplo de la lotería para mostrar como podemos evaluar distintas expresiones. Pero ya en el final de la clase, notamos que el uso abusivo del else if para evaluar multiples escenarios en base a una sola variable, puede ser problemático a largo plazo. Para esto tenemos el When.

El viejo Switch de Java

Si trabajaron con Java, el antecesor de Kotlin en el aspecto de Android, saben de lo que hablo. Switch era una sentencia muy usada para evaluar distintos valores de una misma variable. Veamos como se usaba:

switch(monedas) {
        case 5:
            System.out.println("Habitación 1");
            break;
        case 10:
            System.out.println("Habitación 2");
            break;
        case 15:
            System.out.println("Habitación 3");
            break;
        case 20:
            System.out.println("Habitación 4");
            break;
        default:
            System.out.println("Habitación 5");
    }

Este ejemplo lo extraje de este blog y honestamente no termino de entender cual es la relación ente habitaciones y monedas. Pero lo importante es entender la estructura: monedas es una variable que esta siendo evaluada en cinco casos distintos, de los cuales los primeros cuatro son el valor en si, y el último viene a ser una especie de “else”. System.out.println es nuestro println de toda la vida en Kotlin. La sentencia break (hablaremos más en detalle en futuras clases) salta el Switch cuando entra en alguno de los cases. Sin esto, cuando entremos al case 5, pasaríamos por el 10, 15 y 20. Era complicado explicar todo esto en sus tiempos, pero por suerte Kotlin vino a aliviar bastante el asunto. Su When, llevado al mismo ejemplo arriba, sería así:

when (monedas) {
    5 -> println("Habitación 1")
    10 -> println("Habitación 2")
    15 -> println("Habitación 3")
    20 -> println("Habitación 4")
    else -> println("Habitación 5")
}

No se puede negar que Kotlin es un rey en la simplificación. En este caso no necesitamos un break, el salto es automático; y el default de Java es claramente el else. Traigo este ejemplo para que se vea claramente la evolución de esta sentencia.

¡Comencemos!

Podríamos hacer el juego de la lotería más interesante: un sistema de puntos que puedas ganar según la posición en que haya salido tu número. Vamos a resolverlo primero con else if. Definimos una variable score:

var score = 0

Tiene que ser mutable porque vamos a cambiar constantemente el valor de score. Ahora vamos a determinar 5 puntajes dependiendo del resultado del array mezclado:

if(selectedNum?.toInt() == numbers[0]) {
    score =+ 5
} else if(selectedNum?.toInt() == numbers[1]){
    score =+ 4
} else if(selectedNum?.toInt() == numbers[2]){
    score =+ 3
} else if(selectedNum?.toInt() == numbers[3]){
    score =+ 2
} else if(selectedNum?.toInt() == numbers[4]){
    score =+ 1
} else {
    println("Has perdido! El numero era ${numbers[0]}")
    return
}

println("Has ganado! Tu score final es $score")

Por un lado comprobamos que selectedNum este en las posiciones 0, 1, 2, 3 o 4 del array. Si no lo esta, devolvemos el mensaje de derrota. Usamos la sentencia return para no ejecutar todo lo demás, de esa manera cuando ganamos, podemos acceder al print de victoria con la impresión del score. Un detalle interesante es que Intellij entiende que sería una práctica mejor usar un when en este caso:

Y queda convertido en esto:

when {
    selectedNum?.toInt() == numbers[0] -> {
        score =+ 5
    }
    selectedNum?.toInt() == numbers[1] -> {
        score =+ 4
    }
    selectedNum?.toInt() == numbers[2] -> {
        score =+ 3
    }
    selectedNum?.toInt() == numbers[3] -> {
        score =+ 2
    }
    selectedNum?.toInt() == numbers[4] -> {
        score =+ 1
    }
    else -> {
        println("Has perdido! El numero era ${numbers[0]}")
        return
    }
}

Es una buena conversión, pero tengamos en cuenta que no debemos ajustar un poco el código:

  • La expresión selectedNum?.toInt() == numbers[0] se puede evitar pasando la variable al when
  • Las llaves sirven cuando trabajamos con varias lineas, en este caso solo nos serviría para el else

Dicho esto, modifiquemos el código:

when (selectedNum?.toInt()) {
    numbers[0] -> score =+ 5
    numbers[1] -> score =+ 4
    numbers[2] -> score =+ 3
    numbers[3] -> score =+ 2
    numbers[4] -> score =+ 1
    else -> {
        println("Has perdido! El numero era ${numbers[0]}")
        return
    }
}

Como ven, ahorramos muchas lineas de código, además de que se volvió más legible.

Conclusiones

Al igual que if, la sentencia when no pasará desapercibida en nuestros proyectos. La seguiremos usando en las próximas clases dado que hay muchos conceptos que se cruzan con los condicionales, como por ejemplo los rangos.

¡Deja un comentario!

Artículos relacionados

Curso Kotlin | #19. Pair

A veces necesitamos relacionar dos valores y almacenarlos en una variable única, y para ello tenemos a Pair.

Curso Kotlin | #17. Proyecto: The Hero Legacy

Si empezaste esta serie desde cero y ya leíste 16 capítulos, ¡Felicidades! Empezaste a dominar los primeros conceptos fundamentales en Kotlin. Este es el primer paso de tu senda como desarrollador/a. Estamos en una instancia en donde podemos poner en práctica todo lo que aprendiste hasta ahora. Bienvenido/a al primer proyecto de la serie.

Curso Kotlin | #16. Funciones

Las funciones son procedimientos que se pueden reutilizar y nos permiten encapsular comportamientos y mejorar la lectura del código.

Curso Kotlin | #15. Excepciones

Las excepciones en Kotlin nos permiten evitar comportamientos no deseados ante problemas que se presentan en tiempo de ejecución. Por ejemplo cuando se intenta dividir por cero, castear un tipo por otro no válido, intentar agregar un valor a una lista nula, entre otros casos. Hoy vamos a ver su implementación en el código.

Curso Kotlin | #14. Rangos

Cuando hablamos de rangos, nos referimos a un intervalo de números en el sentido matemático. Podemos generar, por ejemplo, un rango que comprenda los números del 1 al 10. Hoy veremos como aplicarlo a los conceptos anteriormente aprendidos.