Is it possible to return the same type as the type parameter when the operator
For example:
fun <T> f(a: T): T =
when (a) {
a is Int -> 0 // if T is Int, then return Int
a is String -> "" // if T is String, then return String
else -> throw RuntimeException() // Otherwise, throw an exception so that the return type does not matter.
}
It gives compilation errors:
Error:(3, 20) The integer literal does not conform to the expected type T
Error:(4, 23) Type mismatch: inferred type is String but T was expected
source to share
Then you can pipe the result T
. You won't get any help from the compiler and you will get warnings, but at least it will compile:
fun <T> f(a: T): T =
when {
a is Int -> 0 // if T is Int, then return Int
a is String -> "" // if T is String, then return String
else -> throw RuntimeException() // Otherwise, throw an exception so that the return type does not matter.
} as T
Note that when (a)
it is not necessary here, just when {
enough.
source to share
Currently, when the Kotlin compiler parses a function, it does not accept certain special cases of type parameter for body parts.
Instead, code that works with a type parameter T
must be correct with any T
. Returning Int
where expected T
is not considered safe just because it is not sufficiently parsed to prove that T
it is always a supertype Int
if a function reaches that branch.
One option is to make an uncontrolled spike on T
, as in @ nhaarman's answer, thereby expressing that you are sure the types are correct.
Another solution is to make several overloads of your function that work with different types:
fun f(a: Int) = 1
fun f(a: String) = ""
fun f(a: Any): Nothing = throw RuntimeException()
In this case, the compiler will choose to overload the function based on the argument you pass, as opposed to specializing one generic function for a specific type argument, and this is an easier task for the compiler since it does not include any type of analysis inside the function body.
Also, a similar question:
source to share