In Kotlin, decision-making in the code can often be simplified and made more intuitive using the when expression. A powerful feature in Kotlin, the when expression is often utilized as a cleaner and more readable substitute for if-else chains. This not only makes your code more concise but also improves its readability and maintainability.
The Traditional If-Else Chain
Before diving into when, let's take a look at how a typical if-else chain might look. For instance, consider the example below which categorizes numbers as positive, negative, or zero:
fun categorizeNumber(number: Int): String {
if (number > 0) {
return "Positive"
} else if (number < 0) {
return "Negative"
} else {
return "Zero"
}
}
While this works perfectly, it can quickly become cumbersome when handling multiple conditions. Enter the when expression.
Introducing the When Expression
A when expression in Kotlin is more flexible and concise. It allows you to replace complex if-else chains elegantly. Here’s how you can simplify the previous logic using when:
fun categorizeNumber(number: Int): String {
return when {
number > 0 -> "Positive"
number < 0 -> "Negative"
else -> "Zero"
}
}
The when expression evaluates each condition sequentially. When a match is found, the block of code following the arrow (->) executes. If no conditions match, the else branch executes, providing a catch-all case similar to the default case in a switch statement.
When as a Statement
The when structure can also be used as a statement, where the purpose is to execute code blocks based on matching conditions, rather than returning a value:
fun printNumberSign(number: Int) {
when {
number > 0 -> println("The number is positive.")
number < 0 -> println("The number is negative.")
else -> println("The number is zero.")
}
}
Branches with Multiple Conditions
when allows you to evaluate multiple conditions in a single branch. This significantly reduces redundancy when multiple inputs need to trigger the same action.
fun getResponse(code: Int): String {
return when (code) {
1, 2, 3 -> "Confirmed"
4, 5, 6 -> "Denied"
7, 8, 9 -> "Pending"
else -> "Unknown"
}
}
In this example, numbers 1, 2, and 3 all lead to the "Confirmed" response.
When and Type Checking (Smart Casts)
The when expression can also perform smart casts. This means that it can determine types at runtime, allowing you to safely call functions specific to that type, without needing explicit casting:
fun handleInput(input: Any) {
when (input) {
is Int -> println("Handle Int: ")
is String -> println("Handle String: ")
else -> println("Unknown type")
}
}
Sealed Classes Advantage
Another compelling use of when is with Kotlin's sealed classes. Sealed classes provide more custom data control by restricting the class hierarchy, allowing you to express a clear structure of your code logic:
sealed class Operation {
object Add : Operation()
object Subtract : Operation()
}
fun executeOperation(op: Operation) {
when(op) {
Operation.Add -> println("Addition")
Operation.Subtract -> println("Subtraction")
}
}
In this scenario, you’re required to handle all possible subclasses, reducing the risk of runtime errors caused by unhandled states.
In conclusion, the when expression in Kotlin provides an elegant, readable, and efficient method for managing conditional logic across your applications. By leveraging the unique structures that when provides, you not only make code easier to read and maintain but also improve its scalability and robustness.