Java and Kotlin are strongly typed languages. It’s not necessary to cast types when working up an object graph. For example
public void sort(Collection col){ //todo } sort(new ArrayList()); sort(new HashSet());
This is an example of polymorphism in Java. ArrayList and HashSet are both Collections so it’s acceptable to pass either types to the example sort method.
Keep in mind this is not a two way street. This code would not compile.
public void sort(List list){ //todo } Collection col = new ArrayList(); sort(col); //Compile error! sort((List) col); //OK
Even though col points at an ArrayList and ArrayList implements List, Java forbids you to pass col to sort without a cast. This is because the compiler has no idea that col is pointing at an ArrayList. Keep in mind this is true of Kotlin also.
Although we can get our code to compile with a cast, it’s still dangerous code. Let’s tweak it a little big and have col point at a HashSet instead of ArrayList.
public void sort(List list){ //todo } Collection col = new HashSet(); //Compiles but throws //ClassCastException sort((List) col);
Now the code compiles, but it will fail at run time. There is no way to cast HashSet to a List. HashSet does not implement List in anyway so when the code attempts to make the cast, the code will fail. We have to use the instanceof operator to make sure the cast is safe first.
public void sort(List list){ //todo } Collection col = new HashSet(); if (col instanceof List){ //Now it's safe sort((List) col); }
This code is now safe. It will check if the runtime type of col is a List first. If the object is a List, it will make the cast. Otherwise, the cast will not get made.
Tutorial
This portion of the Kotlin Koans tutorial shows off how Kotlin handles casting compared to Java. Here is the Java code that needs to get rewrote in Kotlin.
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"); } }
Kotlin has a when
keyword that is used for casting. Here is the equivalent Kotlin code.
fun todoTask8(expr: Expr): Int { when (expr) { is Num -> return expr.value is Sum -> return todoTask8(expr.left) + todoTask8(expr.right) else -> throw IllegalArgumentException("Unknown expression") } }
As usual, Kotlin is more concise than Java. The when
block starts with the when
followed by the variable in question. You can have any number of is
clauses in this statement followed by the type. The variable is automatically cast to the specified type on the right hand side of the -> operator.
You can click here to see Part 8
One thought on “Kotlin Koans—Part 9”