Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin method overloading

This following declaration is legal in Kotlin.

fun foo(): String = "foo_1"
fun <T> foo(): T = "foo_2" as T

As bytecode we are getting:

public final static foo()Ljava/lang/String;

// signature <T:Ljava/lang/Object;>()TT;
// declaration: T foo<T>()
public final static foo()Ljava/lang/Object;

It's also possible to call both of these methods from Kotlin.

The problem comes when I'm trying to call any of them from Java:

ClassKt.foo()

Ambiguous call. Both methods match ...

How to avoid such a problem? How to deal with such methods? What if 3-rd party kt library has same issue?

The example above is a synthetic one.

like image 381
Sergei Rybalkin Avatar asked Aug 25 '18 19:08

Sergei Rybalkin


People also ask

Does Kotlin allow operator overloading?

Operator overloading Kotlin allows you to provide custom implementations for the predefined set of operators on types. These operators have predefined symbolic representation (like + or * ) and precedence.

What is overloaded method in Scala?

What is Scala Method Overloading? Scala Method overloading is when one class has more than one method with the same name but different signature. This means that they may differ in the number of parameters, data types, or both. This makes for optimized code.

What is method overloading Swift?

In Swift, two or more functions may have the same name if they differ in parameters (different number of parameters, different types of parameters, or both). These functions are called overloaded functions and this feature is called function overloading.


1 Answers

Why does it work with Kotlin to begin with... In Java having two methods like:

private static String test() {
    return "";
}

private static <T> T test() {
    return null;
}

would result in a compile time error. And for java devs this is sort of obvious, these methods would have the same type erasure. But this is rule imposed by javac, not by the JVM where this code runs. So javac does not treat two methods as having only a different return type as overloads. Well, kotlin is a different language and since it runs on the JVM (that expects valid byte-code) it allows treating methods with only the return type being different as overloads. I am yet to look at the byte code and understand how that happens; it also seems that this will work only for generic code, so may be type erasure is slightly different in case of kotlin.

Now, things should be obvious why calling such a method from java fails. Kotlin offers a neat solution for this: @JvmName("someDistinctName"). I am not entirely sure how this works under the hood either... yet, though I assume this will create a bridge method.

EDIT

@JvmName will rename the method at the byte-code level.

like image 165
Eugene Avatar answered Nov 02 '22 07:11

Eugene