Class implements "matching" Kotlin and Java interfaces, works better in Java?


I had a pair of “matching” interfaces in Kotlin and Java (used from two different Android modules that don’t have access to each other), like so:


    boolean isDebugEnabled();
    boolean isInTestMode();
    void signOut();


    val isDebugEnabled: Boolean
    val isInTestMode: Boolean
    fun signOut()

I had a java class that implemented both interfaces using signatures like the Java interface above, and it satisfied the Kotlin interface as expected. This is fine, been living with this for months.

…but then I tried to convert the Java class to Kotlin and the symmetry was broken. I could not satisfy both interfaces no matter what I did. Tried splashing in some annotations to the fields, didn’t matter. I get a message from the linter “Accidental override, the following declarations have the same signature”. Tried splashing in @JvmName in places, @JvmField in other places, nothing worked. This modality of Java->Kotlin interface only works if I implement using a Java class.

…or am I missing something?

(Obviously this is easily worked around by changing one or both of the interfaces, but I really like the way it worked before! :slight_smile:)


You can’t use a single Kotlin method or property to implement both a property from one base interface and a method from another base interface.


So I surmised. But why? It works the “other way” (implementing a Kotlin field from a Kotlin interface and a Java accessor from another in a Java class.)


Because a Kotlin property and a Kotlin method are distinct things, and a Java method is seen either as a Kotlin method or a Kotlin property depending on its name.


Right, but in this case, the accessor method prototype is in Java, not Kotlin. The Kotlin->Java integration already does “automagic” mapping between getSomeProperty() methods to Kotlin vals. (At least, it does so at call site invocation.)


I guess it’s just a call that had to be made WRT interop: Kotlin class implementing Java interface is less “magic” because you’re on the Kotlin-side of the world, so it’s harder to reason about why there should be magic. At any rate, it’s a small matter to live with.