如何克服"相同的JVM签名"实现Java接口时出错?

时间:2015-03-25 23:33:56

标签: kotlin

使用下面的代码,我在IntelliJ IDEA 13.1.6和Kotlin插件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类JavaInterface.java

public interface JavaInterface {
  public String getName();
}

Kotlin课程,KotlinClass.kt

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

我已经尝试重写“getter”&#39;方法 添加override fun getName(): String? = name,但会产生相同的错误。

我可以通过这样做来看到一种解决方法:

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

但在我的实际案例中,我有很多要实现的属性,也需要setter。为每个房产做这件事并不像Kotlin-ish。我错过了什么?

9 个答案:

答案 0 :(得分:32)

使变量private解决问题。

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

答案 1 :(得分:3)

另一种解决方法是在抽象的Kotlin类中声明属性,然后编写一个扩展KotlinClass并实现JavaInterface的小型java类。

// 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.
}

答案 2 :(得分:3)

您可以使用@JvmField来指示编译器不生成getter / setter,并且可以实现setter和getter。有了这个,你的代码在Java(作为属性getter / setter)和Kotlin作为属性

中运行良好

实施例: 的 JAVA

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

<强>科特林

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

答案 3 :(得分:2)

如果您可以直接控制界面,那么最好的方法是在Kotlin中编写界面。然后你可以写你的班级

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

仍然使用与以前相同的接口从任何Java代码引用它。这看起来比将所有属性设置为private并覆盖get函数要简洁得多。显然,如果您不能将接口迁移到Java,因为您不拥有它,那么这似乎是唯一的解决方案。

答案 4 :(得分:1)

我们发现,要使用相同的名称而不发生冲突,ctor args必须私有 AND 您必须仍覆盖接口方法。您不需要任何其他支持字段。此外,您的表达式正文赋值不会递归,因此您可以安全地使用该语法。

Java接口

<button id="loginButton">Button</button>

$('#loginButton').click(function() {
  $('#login-form').modal();
});

Kotlin Class

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

答案 5 :(得分:0)

public interface JavaInterface {
    public String getName();
}

public class KotlinClass(val namePrivate: String?) : JavaInterface {

private var name = namePrivate

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

答案 6 :(得分:0)

恕我直言,最易读的组合是通过单表达式功能(@Renato Garcia和@Steven Spungin的答案的组合)的字段+显式接口实现:

Java:

public inteface SomeInterface {
    String getFoo();
}

科特琳:

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

答案 7 :(得分:0)

将变量重命名为其他名称,或者如果您不希望将其公开,则将其设为私有。

答案 8 :(得分:0)

名为@JvmName的Kotlin注释功能将解决Java和Kotlin具有相同签名时的重复问题。

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

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

使用JvmName将是:

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

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