Learning Kotlin: Smart Casts

Submitted by Robert MacLean on Tue, 06/26/2018 - 09:00
**More Information** * [Code for this Koan can be found here](https://github.com/Kotlin/kotlin-koans/tree/master/src/i_introduction/_8_Smart_Casts). * This is the 9th post in a multipart series. If you want to read more, see our [series index](/learning-kotlin-introduction) The goal of this Koan is to show how smart the Kotlin compiler is; in that when you use something like the `is` keyword to handle type checking the compiler will then know the type later on and be able to use it intelligently. So if we want to check types in Java we would use something like this where we would use `instanceof` to check the type and then cast it to the right type. public class JavaCode8 extends JavaCode {     public int eval(Expr expr) {         if (expr instanceof Num) {             return ((Num) expr).getValue();         }         if (expr instanceof Sum) {             Sum sum = (Sum) expr;             return eval(sum.getLeft()) + eval(sum.getRight());         }         throw new IllegalArgumentException("Unknown expression");     } } In Kotlin we, by checking the type the compiler handles the casting for us, but before we get to that we also got to learn about the [when](https://kotlinlang.org/docs/reference/control-flow.html#when-expression) which is the Kotlin form of [the Switch keyword](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/switch) in C# or Java and it offers similar functionality, as shown in this example: when (x) {     1 -> print("x == 1")     2 -> print("x == 2")     else -> { // Note the block         print("x is neither 1 nor 2")     } } and it supports multiple values on the same branch when (x) {     0, 1 -> print("x == 0 or x == 1")     else -> print("otherwise") } Where it gets awesome, is the extra actions it supports; for example `when` values can be functions, not just constants: when (x) {     parseInt(s) -> print("s encodes x")     else -> print("s does not encode x") } You can also use `in` or `!in` to check values in a range/collection: when (x) {     in 1..10 -> print("x is in the range")     in validNumbers -> print("x is valid")     !in 10..20 -> print("x is outside the range")     else -> print("none of the above") } It really is very cool, so let us see how we use Smart Casts and `when` together and how it compares with the Java code above: fun eval(e: Expr): Int =     when (e) {         is Num -> e.value         is Sum -> eval(e.left) + eval(e.right)    } Really nice and, I think, more readable than the Java code.