如何在实现 Java 接口时克服 "same JVM signature" 错误?
How to overcome "same JVM signature" error when implementing a Java interface?
使用下面的代码,我在 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 class, JavaInterface.java
:
public interface JavaInterface {
public String getName();
}
Kotlin class、KotlinClass.kt
public class KotlinClass(val name: String?) : JavaInterface
我试过重写 'getter' 方法
添加 override fun getName(): String? = name
,但会产生相同的错误。
我可以通过这样做找到一种解决方法:
public class KotlinClass(val namePrivate: String?) : JavaInterface {
override fun getName(): String? = namePrivate
}
但在我的真实案例中,我有许多属性需要实现并且也需要设置器。为每个 属性 执行此操作似乎不太像 Kotlin。我错过了什么?
另一种解决方法是在抽象 Kotlin class 中声明属性,然后编写一个扩展 KotlinClass 并实现 JavaInterface 的小 java class。
// 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.
}
使该变量 private
解决了问题。
public class KotlinClass(private val name: String?) : JavaInterface
public interface JavaInterface {
public String getName();
}
public class KotlinClass(val namePrivate: String?) : JavaInterface {
private var name = namePrivate
override fun getName(): String? {
return name
}
}
我们发现要使用相同的名称而不发生冲突,ctor args 必须 private AND 你必须 仍然覆盖 接口方法。您不需要任何 额外的 支持字段。此外,您的表达式主体赋值不会递归,因此您可以安全地使用该语法。
Java 界面
interface IUser {
String getUserScope();
String getUserId();
}
科特林 Class
class SampleUser(private val userScope: String, private val userId: String) : IUser {
override fun getUserId() = userId
override fun getUserScope() = userScope
}
您可以使用@JvmField 指示编译器不生成 getter/setter,并且您可以实现您的 setter 和 getter。有了这个,您的代码在 Java(作为属性 getter/setter)和 Kotlin 作为 属性
中运行良好
示例:
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")
}
}
如果您可以直接控制界面,那么最好的方法是用 Kotlin 编写界面。然后你可以写下你的 class
public class KotlinClass(override val name: String?) : KotlinInterface
并且仍然使用与以前相同的界面从任何 Java 代码中引用它。这看起来比将所有属性设置为私有并覆盖 get 函数要简洁得多。显然,如果您不能将接口迁移到 Java,因为您不拥有它,那么这似乎是唯一的解决方案。
恕我直言,最具可读性的组合是字段+通过单表达式函数实现的显式接口(@Renato Garcia 和@Steven Spungin 的答案的组合):
Java:
public inteface SomeInterface {
String getFoo();
}
科特林:
class Implementation(@JvmField val foo: String) : SomeInterface {
override fun getFoo() = foo
}
将变量重命名为其他名称,或者如果您不想将其设为私有,则将其设为私有 public。
Kotlin注解特性@JvmName
将解决Java和Kotlin签名相同时的重复问题
fun function(p: String) {
// ...
}
// Signature: function(Ljava/lang/String)
与JvmName
一起使用将是:
@JvmName("functionOfKotlin")
fun function(p: String) {
// ...
}
// Signature: functionOfKotlin(Ljava/lang/String)
将函数转换为 属性,而不是从函数初始化 属性。
例如:
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
}
至
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
}
使用下面的代码,我在 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 class, JavaInterface.java
:
public interface JavaInterface {
public String getName();
}
Kotlin class、KotlinClass.kt
public class KotlinClass(val name: String?) : JavaInterface
我试过重写 'getter' 方法
添加 override fun getName(): String? = name
,但会产生相同的错误。
我可以通过这样做找到一种解决方法:
public class KotlinClass(val namePrivate: String?) : JavaInterface {
override fun getName(): String? = namePrivate
}
但在我的真实案例中,我有许多属性需要实现并且也需要设置器。为每个 属性 执行此操作似乎不太像 Kotlin。我错过了什么?
另一种解决方法是在抽象 Kotlin class 中声明属性,然后编写一个扩展 KotlinClass 并实现 JavaInterface 的小 java class。
// 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.
}
使该变量 private
解决了问题。
public class KotlinClass(private val name: String?) : JavaInterface
public interface JavaInterface {
public String getName();
}
public class KotlinClass(val namePrivate: String?) : JavaInterface {
private var name = namePrivate
override fun getName(): String? {
return name
}
}
我们发现要使用相同的名称而不发生冲突,ctor args 必须 private AND 你必须 仍然覆盖 接口方法。您不需要任何 额外的 支持字段。此外,您的表达式主体赋值不会递归,因此您可以安全地使用该语法。
Java 界面
interface IUser {
String getUserScope();
String getUserId();
}
科特林 Class
class SampleUser(private val userScope: String, private val userId: String) : IUser {
override fun getUserId() = userId
override fun getUserScope() = userScope
}
您可以使用@JvmField 指示编译器不生成 getter/setter,并且您可以实现您的 setter 和 getter。有了这个,您的代码在 Java(作为属性 getter/setter)和 Kotlin 作为 属性
中运行良好示例: 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")
}
}
如果您可以直接控制界面,那么最好的方法是用 Kotlin 编写界面。然后你可以写下你的 class
public class KotlinClass(override val name: String?) : KotlinInterface
并且仍然使用与以前相同的界面从任何 Java 代码中引用它。这看起来比将所有属性设置为私有并覆盖 get 函数要简洁得多。显然,如果您不能将接口迁移到 Java,因为您不拥有它,那么这似乎是唯一的解决方案。
恕我直言,最具可读性的组合是字段+通过单表达式函数实现的显式接口(@Renato Garcia 和@Steven Spungin 的答案的组合):
Java:
public inteface SomeInterface {
String getFoo();
}
科特林:
class Implementation(@JvmField val foo: String) : SomeInterface {
override fun getFoo() = foo
}
将变量重命名为其他名称,或者如果您不想将其设为私有,则将其设为私有 public。
Kotlin注解特性@JvmName
将解决Java和Kotlin签名相同时的重复问题
fun function(p: String) {
// ...
}
// Signature: function(Ljava/lang/String)
与JvmName
一起使用将是:
@JvmName("functionOfKotlin")
fun function(p: String) {
// ...
}
// Signature: functionOfKotlin(Ljava/lang/String)
将函数转换为 属性,而不是从函数初始化 属性。 例如:
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
}
至
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
}