Reputation: 338
I am trying to achieve something analagous to the following toy example:
fun getBoolean() = true
fun getFloat() = 1.0F
fun getInt() = 1
fun getLong() = 1L
fun getString() = "foobar"
fun <T> extract(defaultVal: T): T = when (defaultVal) {
is Boolean -> getBoolean() as T
is Float -> getFloat() as T
is Int -> getInt() as T
is Long -> getLong() as T
is String -> getString() as T
else -> defaultVal
}
Is there a way to achieve this without the unchecked cast as T
in the different cases?
Removing the unchecked casts results in a compiler error whereby the return type is the type of the function, and not T
. I feel like the compiler should be able to infer T
by the defaultVal is ____
in the when
statement here in a similar way to smart casting:
fun usesInt(arg: Int) = arg + 1
fun <T> extract(defaultVal: T): T = when (defaultVal) {
// ...
is Int -> {
usesInt(defaultVal) // defaultVal is smart cast to Int => T is Int
getInt() as T
}
// ...
}
Is this a shortcoming in the smart cast/inference system, or am I missing something here?
Upvotes: 1
Views: 728
Reputation: 93521
First of all, that would be an invalid assumption to make when casting. Consider this:
open class Base
class Derived: Base()
fun getBoolean() = true
fun getBase() = Base()
fun <T> extract(defaultVal: T): T = when (defaultVal) {
is Boolean -> getBoolean() as T
is Base -> getBase() as T
else -> defaultVal
}
Then if you do this:
val extracted: Derived = extract(Derived())
You'll get a ClassCastException because it's trying to cast a Base to a Derived.
I suppose they could make it more sophisticated and check if the classes are open
or not, but this would be stepping through a lot of logic. If it was this sophisticated in all areas, I think compilation would be super slow.
Secondly, casting to a generic type is always going to give you an unchecked cast warning since generic types can't be checked at all. The alternative is making the function inline
and the type reified
. Then it's not an unchecked cast, but you will still get a ClassCastException if you make the mistake above.
Upvotes: 3