Expresión If
El primer control de flujo que vamos a ver en Kotlin es if
, el cual es una expresión, por tanto tiene que devolver un valor. Por lo tanto no hay un operador ternario.
// Uso tradicional var max = a if (a < b) max = b // Con else var max: Int if (a > b) { max = a } else { max = b } // Como expresión val max = if (a > b) a else b
Las ramas if
pueden ser bloques, y la última expresión es el valor de un bloque:
val max = if (a > b) { print("Choose a") a } else { print("Choose b") b }
Si estás usando if
como una expresión en lugar de como una declaración (por ejemplo, devolviendo su valor o asignandoló a una variable), la expresión requiere de una rama else
.
Expresión When
Otro control de flujo sería when
, el cual reemplaza el operador switch de los lenguajes C-like. Su forma más simple es la siguiente:
when (x) { 1 -> print("x == 1") 2 -> print("x == 2") else -> { print("x no es ni 1 ni 2") } }
when
relaciona su argumento con todas las ramas secuencialmente hasta que alguna rama cumple la condición. when
puede utilizarse tanto como expresión como una declaración. Si se usa como una expresión, el valor de que satisface la condición será el valor de toda la expresión. Si se usa como una declaración, los valores de las ramas individuales se ignoran. Al igual que if
, cada rama puede ser un bloque, y su valor es el valor de la última expresión en el bloque.
La rama else
se evalúa si ninguna de las otras condiciones cumplen la condición. Si when
se utiliza como una expresión, la rama else
es obligatoria, a menos que el compilador pueda comprobar que todos los casos posibles están expuestos en todas las ramas de condiciones (, por ejemplo, la clase enum
y los subtipos de las sealed class
).
Si muchos casos se deben gestionar del mismo modo, las ramas de condiciones pueden combinarse con una coma:
when (x) { 0, 1 -> print("x es 0 o 1") else -> print("x es distinto de 0 o 1") }
Podemos utilizar expresiones arbitrarias (no solo constantes) como ramas de condiciones:
when (x) { parseInt(s) -> print("s codifica a x") else -> print("s no codifica a x") }
También se puede comprobar si un valor está dentro de un rango o de una colección:
when (x) { in 1..10 -> print("x está en el rango") in miColeccion -> print("x está en la colección") !in 10..20 -> print("x no está en el rango") else -> print("No es ninguna de las anteriores opciones") }
Otra posibilidad es comprobar si un valor es de un tipo o no. Gracias a los smart casts, puedes acceder a los métodos y propiedades de un tipo sin ninguna comprobación adicional.
fun comprobarPrefijo(x: Any) = when(x) { is String -> x.startsWith("Prefijo") else -> false }
when
puede utilizarse también como reemplazo de una cadena if-else
. Si no se proporciona un argumento, las ramas de condiciones son básicamente expresiones booleanas, y una rama se ejecuta cuando su condición se cumple.
when { x.isOdd() -> print("x es impar") x.isEven() -> print("x es par") else -> print("x es otra cosa") }
Es posible asignarle el valor de un when
a una variable:
fun Request.getBody() = when (val response = executeRequest()) { is Success -> response.body is HttpError -> throw HttpException(response.status) }
Bucles For
Para el control de flujo también existen los bucles. Un bucle for
repite una operación en función del iterador que proporciones.
La sintaxis es la siguiente:
for (item in collection) print(item)
Aunque también se puede usar un bloque:
for (item: Int in ints) { // ... }
Para iterar a través de un rango de números, utiliza una expresión de rango:
for (i in 1..3) { println(i) } for (i in 6 downTo 0 step 2) { println(i) }
Un bucle for
sobre un rango o un array se compila a un bucle basado en índices que no crea un objeto iterator.
Para iterar a través de un array o una lista con un índice se haría del siguiente modo:
for (i in array.indices) { println(array[i]) }
Alternativamente, puedes utilizar la función librería withIndex
:
for ((index, value) in array.withIndex()) { println("El elemento $index es $value") }
Bucles While
while
y do..while
funcionan como en otros lenguajes:
while (x > 0) { x-- } do { val y = retrieveData() } while (y != null) // 'y' es visible
Break y Continue en bucles
Kotlin soporta los operadores clásicos break
y continue
.