Hello! Welcome to the fifth lesson in our "Learn Kotlin Syntax" course.
In our previous lesson, we covered Kotlin's powerful for loop, exploring how to iterate over collections, ranges, and progressions. You learned how to write clean, idiomatic loops that are a significant step up from traditional C-style for loops.
Today, we continue our exploration of control flow by focusing on a feature that makes Kotlin code more concise and expressive. The learning outcome for this lesson is to write an 'if' statement as an expression that returns a value. In Java, if is a statement—it performs an action but doesn't resolve to a value. In Kotlin, if can be an expression, which allows you to write cleaner, more functional-style code, often avoiding the need for mutable variables.
1. From if Statement to if Expression
Let's start with what's familiar. In Kotlin, you can write a traditional if-else statement that looks almost identical to Java's.
Consider this code to find the maximum of two numbers:
fun main() {
val a = 10
val b = 20
var max: Int // A mutable variable is needed here
if (a > b) {
max = a
} else {
max = b
}
println("The maximum value is $max")
}
This works, but it requires declaring a mutable variable max with var and assigning it a value in different code branches. Kotlin offers a more elegant solution by treating if as an expression that returns a value.
This video provides a clear demonstration of this transformation.
Kotlin IF as Expression. Kotlin Tutorials for Android #5.1
The video 'Kotlin IF as Expression' from Smartherd clearly contrasts the traditional if statement with the more idiomatic if expression.
Watch from 00:22 to 02:08. The first part (until 01:19) shows the traditional if-else statement, similar to the Java style. The second part refactors this into a concise if expression, assigning the result directly to a variable.
As you saw in the video, we can rewrite the code above like this:
fun main() {
val a = 10
val b = 20
val max = if (a > b) {
a
} else {
b
}
println("The maximum value is $max")
}
Notice the key improvements:
- The result of the
if-elseblock is directly assigned to themaxvariable. - We can declare
maxas a read-only variable usingval, which is preferred in modern development for promoting immutability and reducing side effects.
2. Syntax Rules and the Ternary Operator
Using if as an expression comes with a few important rules. The following reading from Programiz covers these points and draws a useful parallel to a familiar Java feature.
Kotlin if...else Expression (With Examples)
This article, 'Kotlin if...else Expression (With Examples)', explains the core rules and provides clear examples.
Read the sections 'Kotlin if expression' and 'Example: Kotin if expression'. Pay close attention to the mandatory else branch and the comparison to Java's ternary operator.
Let's summarize the key points from the article:
-
The
elsebranch is mandatory: When you useifas an expression, you must provide anelsebranch. This makes sense, as an expression must always evaluate to a value, and without anelse, the expression would have no value if theifcondition were false. -
No ternary operator in Kotlin: As the article notes, the
ifexpression effectively replaces Java's ternary operator (condition ? exprIfTrue : exprIfFalse). The Kotlin version is often considered more readable.- Java:
val max = (a > b) ? a : b; - Kotlin:
val max = if (a > b) a else b
For single-line branches, you can omit the curly braces
{}, making the syntax very similar to the ternary operator. - Java:
3. if Expressions with Multi-line Blocks
What if your if or else branches need to do more than just return a value? For example, you might want to log a message before returning.
When a block (the code inside {...}) contains multiple expressions, the last expression in the block is the return value. All preceding lines are executed as usual.
Let's watch the final part of the Smartherd video, which demonstrates this concept perfectly.
Kotlin IF as Expression. Kotlin Tutorials for Android #5.1
This segment explains how multi-line blocks work within an if expression.
Watch from 02:08 to 03:40. Notice how println statements are executed, but the final value (a or b) is what gets returned and assigned to the max variable.
Here is the code pattern from the video, which is also demonstrated in the Programiz article you read earlier:
val a = -9
val b = -11
val max = if (a > b) {
println("$a is larger than $b.")
println("max variable holds value of a.")
a // This is the last expression, so it's the return value
} else {
println("$b is larger than $a.")
println("max variable holds value of b.")
b // This is the last expression, so it's the return value
}
println("max = $max")
This feature is powerful because it allows you to perform side effects (like logging) while still using the concise expression-based syntax.
4. Hands-On Practice
Let's apply this to a scenario you might encounter in backend development. Imagine you're writing a function that returns a status message based on an HTTP response code.
Goal: Write a function that takes an integer statusCode and returns a descriptive String.
- In your IDE, create a new Kotlin file and a
mainfunction. - Inside
main, define a functionfun getStatusMessage(statusCode: Int): String. - Inside
getStatusMessage, use anif-else-if-elseexpression to return the correct message:- If
statusCodeis200, return"OK". - If
statusCodeis404, return"Not Found". - If
statusCodeis500, return"Internal Server Error". - For any other code, return
"Unknown Status".
- If
- From your
mainfunction, callgetStatusMessagewith a few different codes (e.g.,200,404,403) and print the results to verify your logic.
Click to see a possible solution
fun getStatusMessage(statusCode: Int): String {
return if (statusCode == 200) {
"OK"
} else if (statusCode == 404) {
"Not Found"
} else if (statusCode == 500) {
"Internal Server Error"
} else {
"Unknown Status"
}
}
fun main() {
val status200 = getStatusMessage(200)
println("Code 200: $status200") // Expected: OK
val status404 = getStatusMessage(404)
println("Code 404: $status404") // Expected: Not Found
val status403 = getStatusMessage(403)
println("Code 403: $status403") // Expected: Unknown Status
}
Note: Since the function body is just a single expression, you could make it even more concise with an expression body: fun getStatusMessage(statusCode: Int): String = if (statusCode == 200) "OK" else if ...
Conclusion
In this lesson, you've learned how to leverage one of Kotlin's key features: using if as an expression. This allows for more declarative, readable, and safer code by favoring immutable val declarations over mutable var variables.
Key Takeaways:
- In Kotlin,
ifcan be used as an expression that returns a value. - When used as an expression, the
elsebranch is mandatory to ensure a value is always returned. - This feature replaces the need for a ternary operator and is often more readable.
- In a multi-line
iforelseblock, the value of the last expression is returned. - Using
ifexpressions helps in writing more functional-style code and promotes immutability.
Next Lesson Preview:
While if-else-if ladders work well, Kotlin provides an even more powerful and readable construct for handling multiple conditions: the when expression. In our next lesson, you'll learn how to use when to replace traditional switch statements and complex if-else-if chains, making your conditional logic even cleaner.