Is there any difference between these two Kotlin extension functions?
fun Any?.f(o: Any?) = 100
fun <T> T.g(o: T) = 100
Is it possible to rewrite g
in such a way that the type of its argument and receiver are forced to be the same?
That is, 10.g(5)
and "x".g("y")
are OK, but 10.g("y")
does not compile.
Edit: Given this, I guess the answer to my second question is no, uless one adds additional arguments.
CodePudding user response:
I believe this is not possible officially at the time of writing this answer (Kotlin 1.7.20).
However, internally Kotlin compiler supports such case, it allows to change the default behavior and use exact type parameters. This is controlled by the internal @Exact
annotation and it is used in many places across the Kotlin stdlib.
With some hacking we can enable this behavior in our own code:
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun <T> @kotlin.internal.Exact T.g(o: @kotlin.internal.Exact T) = 100
Of course, this is purely a hack and it may stop working in future versions of Kotlin.
Update
Answering your first question on whether there is a difference between using Any
and T
. Generic functions make the most sense if the type parameter is not only consumed, but also passed somewhere further. For example, if the function returns T
or it receives an object that consumes T
:
fun main() {
var result = 5.g(7)
}
fun <T> T.g(o: T): T = if (...) this else o
In this case result
is of type Int
. If we use Any
instead of T
, result
would have to be Any
as well.