How to overcome "same JVM signature" error when implementing a Java interface?

Kotlin

Kotlin Problem Overview


With the code below, I am getting the following error in IntelliJ IDEA 13.1.6 and Kotlin plugin 0.11.91.AndroidStudio.3:

Platform declaration clash: The following declarations have the same JVM signature (getName()Ljava/lang/String;):
  • public open fun getName(): kotlin.String?
  • internal final fun <get-name>(): kotlin.String?

Java class, JavaInterface.java:

public interface JavaInterface {
  public String getName();
}

Kotlin class, KotlinClass.kt

public class KotlinClass(val name: String?) : JavaInterface

I've tried overriding the 'getter' method by adding override fun getName(): String? = name, but that produces the same error.

I can see one workaround by doing this instead:

public class KotlinClass(val namePrivate: String?) : JavaInterface {
  override fun getName(): String? = namePrivate
}

But in my real-world case I have a number of properties to implement and need setters too. Doing this for each property doesn't seem very Kotlin-ish. What am I missing?

Kotlin Solutions


Solution 1 - Kotlin

Making that variable private solves the problem.

public class KotlinClass(private val name: String?) : JavaInterface

Solution 2 - Kotlin

You could use @JvmField for instructs the compiler not generate getter/setter, and you can implement your setters and getters. With this your code work well in Java (as attribute getter/setter) and Kotlin as property

Example: JAVA:

public interface Identifiable<ID extends Serializable> 
{
   ID getId();
} 

KOTLIN:

class IdentifiableImpl(@JvmField var id: String) :Identifiable<String> 
{
   override fun getId(): String 
   {
       TODO("not implemented")
   }
}

Solution 3 - Kotlin

The annotation feature of Kotlin named @JvmName will solve the duplication problem in Java and Kotlin when having the same signature.

fun function(p: String) {
   // ...
}

// Signature: function(Ljava/lang/String)

With the use of JvmName will be:

@JvmName("functionOfKotlin")
fun function(p: String) {
   // ...
}

// Signature: functionOfKotlin(Ljava/lang/String)

Solution 4 - Kotlin

IMHO most readable combination is field + explicit interface implementation by the single-expression function (combination of @Renato Garcia's and @Steven Spungin's answers):

Java:

public inteface SomeInterface {
    String getFoo();
}

Kotlin:

class Implementation(@JvmField val foo: String) : SomeInterface {
    override fun getFoo() = foo
}

Solution 5 - Kotlin

Another work-around is to declare the properties in an abstract Kotlin class, then write a small java class that extends KotlinClass and implements JavaInterface.

// JavaInterface.java
public interface JavaInterface {
    int getFoo();
    void setFoo(int value);
}

// KotlinClass.kt
abstract class KotlinClass(open var foo : Int = 0) {
}

// JavaAdapter.java
class JavaAdapter extends KotlinClass implements JavaInterface {
    // all code in KotlinClass, but can't implement JavaInterface there
    // because kotlin properties cannot override java methods.
}

Solution 6 - Kotlin

We have found that to use the same names without clashing, the ctor args must be private AND you must still override the interfaces methods. You don't need any additional backing fields. Also, your expression body assignment will not recurse, so you can safely use that syntax.

Java Interface

interface IUser {
    String getUserScope();
    String getUserId();
}

Kotlin Class

class SampleUser(private val userScope: String, private val userId: String) : IUser {
    override fun getUserId() = userId
    override fun getUserScope() = userScope
}

Solution 7 - Kotlin

If you have direct control over the interface then the best approach is to write the interface in Kotlin. You can then write your class

public class KotlinClass(override val name: String?) : KotlinInterface

and still reference it from any Java code using the same interface as before. This looks a lot neater than setting all the properties to private and overriding the get function. Obviously if you can't migrate the interface to Java because you don't own it then that seems to be the only solution.

Solution 8 - Kotlin

Rename the variable to something else, or make it private if u dont want it to be public.

Solution 9 - Kotlin

public interface JavaInterface {
    public String getName();
}

public class KotlinClass(val namePrivate: String?) : JavaInterface {
	
private var name = namePrivate

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

Solution 10 - Kotlin

convert function to property instead of initializing property from a function. for ex:

    fun getCountriesList(): List<Country> {
    val countries = mutableListOf<Country>()
    countries.add(Country("in", "+91", "India", R.drawable.indian_flag))
    countries.add(Country("us", "+1", "United States",R.drawable.us_flag))
    return countries
}

to

 val countriesList: List<Country>
    get() {
        val countries = mutableListOf<Country>()
        countries.add(Country("in", "+91", "India", R.drawable.indian_flag))
        countries.add(Country("us", "+1", "United States", R.drawable.us_flag))
        return countries
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichael RushView Question on Stackoverflow
Solution 1 - KotlinLKarmaView Answer on Stackoverflow
Solution 2 - KotlinRenato GarciaView Answer on Stackoverflow
Solution 3 - KotlinMahdi-MalvView Answer on Stackoverflow
Solution 4 - KotlinLu55View Answer on Stackoverflow
Solution 5 - KotlinMike BuhotView Answer on Stackoverflow
Solution 6 - KotlinSteven SpunginView Answer on Stackoverflow
Solution 7 - KotlinBarry IrvineView Answer on Stackoverflow
Solution 8 - KotlinM. Usman KhanView Answer on Stackoverflow
Solution 9 - KotlinDmitry HandinView Answer on Stackoverflow
Solution 10 - KotlinMohd QasimView Answer on Stackoverflow