How to make two Java methods have the same name in Kotlin?

64 views Asked by At

In Kotlin, one can use the @JvmName annotation to allow Java to refer to a declaration using a different name. For example, if two Kotlin methods have the same erasure.

@JvmName("doFooWithStrings")
fun doFoo(list: List<String>) {
    ...
}

@JvmName("doFooWithInts")
fun doFoo(list: List<Int>) {
   ...
}

I want to do the opposite - I have two Java methods with different names, because they have the same erasure otherwise. I want these methods to have the same name in Kotlin.

public class Foo {
    public void doFooWithStrings(List<String> list) { ... }

    public void doFooWithInts(List<Integer> list) { ... }
}
// I want users to use doFoo to refer to both of the above in Kotin
doFoo(listOf("1", "2", "3")) // calls doFooWithStrings
doFoo(listOf(1, 2, 3)) // calls doFooWithInts

Is there any annotation that allows me to specify a KotlinName or something like that? The original Java method names should ideally not be accessible from Kotlin, or at least, show a warning so that people are discouraged from using them.

1

There are 1 answers

0
Sweeper On

I couldn't find an annotation like that, but a workaround would be to write extension functions in Kotlin that act as wrappers for the Java methods. The Java methods can be marked @kotlin.Deprecated (not @java.lang.Deprecated!).

import kotlin.Deprecated;
import kotlin.ReplaceWith;

public class Foo {

    @Deprecated(
            message = "Use doFoo instead",
            replaceWith = @ReplaceWith(expression = "doFoo(list)", imports = {})
            // should add the package in which the wrapper extension functions resides into "imports = {}"
    )
    public void doFooWithStrings(List<String> list) { ... }
    @Deprecated(
            message = "Use doFoo instead",
            replaceWith = @ReplaceWith(expression = "doFoo(list)", imports = {})
    )
    public void doFooWithInts(List<Integer> list) { ... }
}
@Suppress("DEPRECATION")
@JvmName("doFooWithStrings") // ironically the wrapper functions also need different JVM names
@JvmSynthetic
fun Foo.doFoo(list: List<String>) {
    doFooWithStrings(list)
}

@Suppress("DEPRECATION")
@JvmName("doFooWithInts")
@JvmSynthetic
fun Foo.doFoo(list: List<Int>) {
    doFooWithInts(list)
}