Given a method which accepts a parameter of a generic type, I would like to check if the type implements Comparable, and if so, compare it with another value.
Assuming the type parameter is T, since T is erased, a test of the form t is Comparable<T>
is not possible, even with reified type parameters. A test of the form t is Comparable<*>
is possible and works, but then t cannot be used as Comparable, because Comparable<*> is out-projected.
fun <T> examine(a: T, b: T) {
if (a is Comparable<*>) {
a <= b
}
}
This fails with:
Kotlin: Out-projected type 'Comparable<*>' prohibits the use of 'public abstract operator fun compareTo(other: T): Int defined in kotlin.Comparable'
The one workaround that I can see is
fun <T> examine(a: T, b: T) {
if (a is Comparable<*>) {
println(a as Comparable<T> <= b)
}
}
which has the unchecked cast, but why is this cast necessary?
Should smart casting not take care of this because of the test we do to check if a is comparable? Are the different type parameters not allowing the smart cast to happen here?
Is this the recommended way to test for Comparable or is there another solution which could avoid unchecked casts?