Konstrukcja when w Kotlinie to potężne narzędzie do zarządzania przepływem wykonania programu, które zastępuje tradycyjny switch-case z Javy. when został wprowadzony w celu zwiększenia wyrazistości, skrócenia kodu boilerplate oraz zwiększenia bezpieczeństwa typów.
W Javie konstrukcja switch-case jest ograniczona tylko do określonych typów (enum, int, String). W przeciwieństwie do Javy, twórcy Kotlina dążyli do uproszczenia gałęzi warunkowych, czyniąc je bardziej wyrazistymi i bezpiecznymi.
Ograniczenia switch-case w Javie utrudniają rozszerzanie i utrzymywanie kodu, szczególnie podczas pracy z kolekcjami, porównywaniem zakresów lub obsługą różnych typów.
Konstrukcja when w Kotlinie jest uniwersalna: działa jako wyrażenie (może zwracać wartość), obsługuje warunki, zakresy, pojedyncze wartości, typy i łączenie warunków.
fun describe(obj: Any): String = when (obj) { 1 -> "Jeden" in 2..10 -> "Od dwóch do dziesięciu" is String -> "String o długości ${obj.length}" else -> "Nieznany" } val res1 = describe(1) // "Jeden" val res2 = describe(5) // "Od dwóch do dziesięciu" val res3 = describe("Kotlin") // "String o długości 6" val res4 = describe(42.0) // "Nieznany"
Czy when może być używane bez argumentu?
Tak, when może być używane jako zamiennik długiego łańcucha if-else, jeśli nie trzeba sprawdzać wartości konkretnej zmiennej.
when { x < 0 -> println("Negatywny") x == 0 -> println("Zero") else -> println("Pozytywny") }
Czy blok else jest obowiązkowy w konstrukcji when?
Blok else nie jest obowiązkowy, jeśli wszystkie możliwe przypadki zostały obsłużone, na przykład, dla enum lub klas sealed. Ale jeśli istnieje prawdopodobieństwo nieobsłużonego przypadku, else jest obowiązkowy, aby uniknąć błędów podczas kompilacji.
sealed class Fruit object Apple : Fruit() object Pear : Fruit() fun check(f: Fruit): String = when (f) { Apple -> "To jest jabłko" Pear -> "To jest gruszka" // Brak bloku else, a kompilator się nie wymądrza — wszystkie warianty zostały uwzględnione }
Czy można w when używać wielu wartości w jednym przypadku?
Tak, wiele wartości można łączyć za pomocą przecinka.
when (value) { 0, 1 -> println("Zero lub Jeden") else -> println("Inne") }
W systemie płatniczym switch-case jest używany do określenia statusu operacji. Przy dodawaniu nowego typu statusu zapomniano zaktualizować switch. Nieobsłużony status prowadzi do silent-error.
Zalety:
Wady:
W Kotlinie używana jest klasa sealed do statusów i konstrukcja when do ich obsługi. Przy dodawaniu nowego statusu kompilator wymaga dodania obsługi nowego przypadku.
Zalety:
Wady: