Baterka
Baterka

Reputation: 3714

Kotlin class that implements Java interface is using default method implementations, rather than overrides

Lets have interface in Java:

public interface Currency {
   default String getName() {
       throw new NotImplementedException("Implement it!");
   }
}

Now I want create an implementation of this interface in Kotlin:

object Dollar : Currency {
     val name = "$"

     override fun getName() {
          return name
     }
} 

If I initialize Dollar class by Dollar() and then call .getName() on it, I am getting NotImplementedException exception.

Why is that? I cannot combine Java interfaces with Kotlin implementations?

Upvotes: 1

Views: 86

Answers (1)

Silvio Mayolo
Silvio Mayolo

Reputation: 70387

Your current code

object Dollar : Currency {
     val name = "$"

     override fun getName(): String {
          return name
     }
}

Produces this error

Dollar.kt:2:6: error: platform declaration clash: The following declarations have the same JVM signature (getName()Ljava/lang/String;):
    fun <get-name>(): String defined in Dollar
    fun getName(): String defined in Dollar
     val name = "$"
     ^
Dollar.kt:4:6: error: platform declaration clash: The following declarations have the same JVM signature (getName()Ljava/lang/String;):
    fun <get-name>(): String defined in Dollar
    fun getName(): String defined in Dollar
     override fun getName(): String {

You've actually declared two functions called getName here as far as the JVM is concerned, you just don't know it yet. Kotlin compiles val declarations into both an internal (private) field and a getter function, which in your case ends up being called getName. Now, you can't have a property name override a Java method getName, even if they'll end up getting compiled to the same name. Kotlin considers the two distinct and the fact that they end up the same is merely an implementation detail. So simply rename your instance variable and the explicit getter will be the only candidate for override.

object Dollar : Currency {
     val _name = "$"

     override fun getName(): String {
          return _name
     }
}

Upvotes: 2

Related Questions