Ce face when
when compară o valoare cu mai multe ramuri, de sus în jos, și execută prima ramură care se potrivește. O ramură poate avea o valoare (1 ->), mai multe valori separate prin virgulă (6, 7 ->), un interval (in 1..4 ->), o verificare de tip (is String ->) sau o expresie. else prinde tot ce a rămas. Nu există „cădere” în ramura următoare, deci nu ai nevoie de break.
Fără valoare între paranteze, when { ... } verifică pe rând condiții Boolean, ca un lanț de if-else if. Ca și if, when este o expresie: val text = when (x) { ... }. Folosit ca expresie trebuie să fie exhaustiv: fie are else, fie acoperă toate cazurile unui enum, sealed sau Boolean.
Poți declara variabila direct în paranteze: when (val r = calcul()) { ... }. Din Kotlin 2.2, o ramură poate avea și o gardă: is Card if suma > 1000 -> ..., adică o condiție în plus după potrivire.
Ce returnează
Folosit ca expresie: valoarea ramurii alese.
Exemple
Exemplul 1: Ziua săptămânii
Ramuri cu o valoare, cu mai multe valori și else. when este folosit ca expresie.
fun numeZi(zi: Int): String = when (zi) {
1 -> "luni"
2 -> "marți"
3 -> "miercuri"
4 -> "joi"
5 -> "vineri"
6, 7 -> "weekend"
else -> "zi invalidă"
}
fun main() {
for (zi in listOf(1, 5, 7, 9)) {
println("$zi: ${numeZi(zi)}")
}
}
Rezultat
1: luni
5: vineri
7: weekend
9: zi invalidă
Exemplul 2: Intervale și when fără argument
in 0..17 verifică un interval. A doua funcție folosește when fără valoare, cu condiții întregi.
fun categorie(varsta: Int) = when (varsta) {
in 0..6 -> "preșcolar"
in 7..17 -> "elev"
in 18..64 -> "adult"
else -> "pensionar"
}
fun livrare(km: Int, greutate: Double) = when {
km <= 5 && greutate < 2 -> "bicicletă"
km <= 50 -> "mașină"
else -> "curier național"
}
fun main() {
println("4 ani: ${categorie(4)}, 15 ani: ${categorie(15)}, 70 ani: ${categorie(70)}")
println("Iași, 3 km, 1 kg: ${livrare(3, 1.0)}")
println("Iași-Pașcani, 75 km: ${livrare(75, 5.0)}")
}
Rezultat
4 ani: preșcolar, 15 ani: elev, 70 ani: pensionar
Iași, 3 km, 1 kg: bicicletă
Iași-Pașcani, 75 km: curier național
Exemplul 3: Tipuri, variabilă în when și gardă
is verifică tipul și face smart cast. Garda if suma > 1000 (Kotlin 2.2) adaugă o condiție la ramură.
sealed interface Plata
data class Card(val suma: Double) : Plata
data class Numerar(val suma: Double) : Plata
data object Voucher : Plata
fun descrie(p: Plata) = when (p) {
is Card if p.suma > 1000 -> "card, sumă mare: cere PIN"
is Card -> "card: ${p.suma} lei"
is Numerar -> "numerar: ${p.suma} lei"
Voucher -> "voucher"
}
fun main() {
listOf(Card(1500.0), Card(80.0), Numerar(20.0), Voucher).forEach { println(descrie(it)) }
when (val rest = 107 % 10) {
0 -> println("număr rotund")
else -> println("restul împărțirii la 10 este $rest")
}
}
Rezultat
card, sumă mare: cere PIN
card: 80.0 lei
numerar: 20.0 lei
voucher
restul împărțirii la 10 este 7
Greșeli frecvente
whenfolosit ca expresie fărăelsepe unIntsauString: eroarea'when' expression must be exhaustive.- Un
elsepus la unwhencare acoperă deja toate valorile unuienumsausealed: compilatorul avertizează că ramura este inutilă. Fărăelse, compilatorul te anunță dacă adaugi un caz nou și uiți să-l tratezi. - Ordinea ramurilor: se alege prima potrivire.
in 0..100pus înainte dein 0..10face a doua ramură inutilă.
Comenzi înrudite
if și else: Execută un bloc doar dacă o condiție este adevărată; în Kotlin if este și expresie, deci întoarce o valoare.is, !is și smart cast: is verifică tipul unei valori; după verificare, compilatorul o tratează automat ca acel tip (smart cast).sealed class și sealed interface: sealed declară o ierarhie închisă: toate subtipurile sunt cunoscute la compilare, deci when le poate verifica pe toate fără else.enum class: enum class declară un tip cu un număr fix de valori numite (zilele săptămânii, stările unei comenzi).Range-uri (.., ..<, until, downTo, step): Intervale de numere sau caractere: .. include capătul, ..< și until îl exclud, downTo numără invers, step sare.