Extension Functions and Types


#1

Hello,

I like the extension functions, really cool stuff. For example:

// Only for MutableList<Int>
fun MutableList<Int>.swap(i1: Int, i2: Int) { … }
// General
fun <T> MutableList<T>.swap(i1: Int, i2: Int) { … }

Then I had the idea, this should also work:

fun testGen(arg: MutableList<Int>) = 1
fun testGen(arg: MutableList<Double>) = 2

But this will never compile :frowning:
Is that maybe a feature in the future?


#2

I am not sure, what do you want to achieve. The line like fun testGen(arg: MutableList<Int>) = 1 defines a new function with signature (MutableList<Int>) -> Int which always returns 1. The second line won’t compile because of platform declaration type clash. You need to change its name for it ti work. But I’ve got a feeling, you want to do something completely different.


#3

MutableList and MutableList are the same type. But in extended functions seems it is somehow two different types.
I asked only: Do A<Int> and A<Doubl\e> be different types in future?


#4

The JVM erases types in runtime. So if you want to use the function somewhere in runtime dispatched block, then no, it won’t work. In some cases you can use inline functions, but the actual solution if types are known in the compile tyme is usually to use @JvmName annotation on one of those functions with a different name (like testGenDouble). In kotlin in will look like the same function is called on different objects. Which one is actually called will be decided in compile time.


#5

Thank you for your response!
That’s true the JVM erases the types. How is it done then with the extension functions? Because you can extend very specific to the generic type (only one time).

class Y<T>
fun Y<Int>.doIt() { println(“Only for Ints…”) }


#6

Extension function resolution is done in compile time and the compiler substitutes the use of extension with call to specific static function in the byte-code. In compile time you have full information about types. You can event use complicated recursive types and type conditions. This is a super-power of Kotlin.


#7

Cool… but now that is not working:

class Y<T>
fun Y<Int>.doIt() { println(“Only for Ints…”) }
fun Y<Double>.doIt() { println(“Only for Doubles…”) }
fun <T> Y<T>.doIt() { println(“For All Others…”) }

This could be solved by the compiler right? My question is, do you think to add this feature to kotlin?


#8

It works like charm if you add @JvmName:

class Y<T>(val value: T)
@JvmName("doInt")
fun Y<Int>.doIt() { println("Only for Ints…") }
@JvmName("doDouble")
fun Y<Double>.doIt() { println("Only for Doubles…") }
fun <T> Y<T>.doIt() { println("For All Others…") }

#9

Thank you!