Instrucciones condicionales II: when



Siguiendo la serie sobre estructuras de selección (ver Instrucciones condicionales I: if), when es otra estructura condicional especialmente útil en situaciones que, evitando if anidados, tenemos que verificar múltiples condiciones.

when comprueba su argumento con cada unas de las ramas de forma secuencial hasta que alguna se cumple y entonces el resto se ignora. Al igual que if, se puede utilizar como una declaración o como una expresión, y en este último caso, devuelve el valor de la rama verificada (y al igual que if, cada rama puede ser un bloque y su valor es el valor de la última expresión del cuerpo del bloque).

when utilizado como una declaración:
val x = 2
when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> { // bloque
        print("x no es ni 1 ni 2")
    }
}
La rama else se evalúa si no se satisface ninguna de las otras condiciones. Observa en el ejemplo anterior que se puede eliminar la rama else y el programa sería correcto. Pero, igual que pasa con if como una expresión, cuando when se usa como una expresión la rama else es obligatoria (a menos que el compilador compruebe que todos los casos posibles están cubiertos).

Si varias condiciones o casos van a manejarse de la misma manera (con las mismas secuencias o instrucciones), esas condiciones se pueden combinar separadas por comas:
val x = 3
when (x) {
    0, 1 -> print("x es igual a 0 o a 1")
    else -> print("x no es ni 0 ni 1")
}
Como condiciones no solo podemos usar valores constantes, también expresiones, por ejemplo:
val x = 3
val s = "3"
when (x) {
    s.toInt() -> print("s convertido a número = $x")
    else -> print("s convertido a número != $x")
}
También podemos verificar si un valor está en un rango o en una colección:
val x = 21
val numeros = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8)    
when (x) {
    in 1..5 -> print("$x está en el rango 1-5")
    in numeros -> print("$x está en el array")
    !in 10..20 -> print("$x está fuera del rango 10-20")
    else -> print("ninguna de las anteriores")
}
Al igual que if, when se puede usar como una expresión y podemos asignar su resultado a una variable:
var diaSemana = 4

var hoy = when(diaSemana) {
    1, 2, 3,4, 5 -> "día laboral"
    6, 7 -> "fin de semana"
    else -> "día desconocido"
}

println("Hoy es $hoy") // Hoy es día laboral
Otra posibilidad es verificar que un valor es o no es de un tipo particular:
fun empiezaPor(x: Any) = when(x) {
    is String -> x.startsWith("K")
    else -> false // rama else obligatoria
}    
println(empiezaPor("Kotlin")) // true
Otro ejemplo:
fun describir(obj: Any): String =
    when (obj) {
        1          -> "Uno"
        "Hola"     -> "Saludo"
        is Long    -> "Long"
        !is String -> "No es un String"
        else       -> "Desconocido"
    }   
    
println(describir(2)) // No es un String
println(describir("Adios")) // Desconocido
También se puede utilizar when sin ningún argumento (como si fuera una sucesión de if- else if) y entonces las condiciones son simplemente expresiones booleanas, ejecutándose la primera rama cuya condición sea verdadera:
val x: Any? = 27

fun esPar(num: Int): Boolean {        
    if (num % 2 == 0) return true        
    return false
}    

when {
    x !is Int -> print("$x no es un número entero")
    x == 0 -> print("$x es cero")
    esPar(x) -> print("$x es un número par")    
    !esPar(x) -> print("$x es un número impar")
    else -> print("$x es otra cosa")
}
Y al igual que con if, podemos utilizar operadores relacionales y lógicos:
val nota1 = 5
val nota2 = 4
when {
    nota1 > 4 && nota2 > 4 -> println("Dos asiganturas aprobadas")
    (nota1 > 4 && nota2 < 5) || (nota1 < 5 && nota2 > 4) -> println("Una asignatura aprobada")
    nota1 < 5 && nota2 < 5 -> println("Dos asignaturas suspendidas")        
}

Comentarios

Entradas populares

I/O: entrada y salida de datos en consola

Recursos gratis para aprender Kotlin

Lectura y escritura de archivos