Hi @darag,
First I’d like to point out that I’m no expert, but I can offer my two cents as to why I think this might be preferable in a language like Kotlin.
TL;DR: I expect it’s because of smart casting and a preference for as?
Whereas in Java, there is only one method of casting (Class) myObj
, in Kotlin there are explicitly two ways myObj as Class
and myObj as? Class
.
Whilst it might be intuitive to imagine that the “unsafe cast” as
which is regularly treated as equivalent to the previous cast in Java might be expected to be used in the same ways, it might actually be used in very different ways.
Whereas in Java you may well have code that you do not want to throw an InvalidCastException
that performs an unsafe cast, in Kotlin, if you are using as
instead of as?
you are almost invariably choosing to accept and handle any TypeCastException
that might be thrown either by accepting responsibility for any that occur at runtime or because they might be explicitly preferred in your code for whatever reason.
Further, if Kotlin were to function as you suggest, you might get some irregularities in code due to “smart casting” objects where objects are of a stricter type than you expect, so for example if you were writing a function that purported to take an “Any” and you decided that the best way would be to handle all types the same way by performing a cast and handling any TypeCastException
…
@Throws(TypeCastException::Class)
fun castingExperiment(a: Any) {
...
return a as TargetClass
...
return a as TargetClass
}
Now, if the compiler initially allowed one of these, but then either
- code was introduced that allowed the compiler to judge that
a
at the second return was never of TargetClass
or
- updates to Kotlin led to improvements to smart casting leading to
as TargetClass
not compiling
Then you might end up having to change that code to throw a TypeCastException
. And importantly, you might not throw it yourself in the same way as the previous call to a as TargetClass
might’ve been doing — leading to slightly different behaviour further down the line.
Also, it might be worth noting that Java code that has something like
if (a instanceof NotTargetClass) {
...
(TargetClass) a
}
Without as
would not be easily portable into Kotlin because of smart casting as it would have to work out to convert it to:
if (a is NotTargetClass) {
...
throw TypeCastException(...)
}
which might both be a large ask on the conversion process and not the code that the programmer was expecting or wanting.
Those are just my thoughts, I’d love to hear what other people might think or if they think that Kotlin would be better with refusing to compile in the case of any such cases.
Thanks.