inheritance - 在 Kotlin 中扩展 Java 类时继承的平台声明冲突

标签 inheritance kotlin java-interop

我正在尝试使用 Kotlin 扩展第三方 Java 类,但我收到以下编译器消息:

Inherited platform declarations clash: The following declarations have the same JVM signature (setCollection(Ljava/util/Collection;)V):

  • fun setCollection(collection:(Mutable)Collection<(raw)Any?>!: Unit defined in KotlinClass

  • fun setCollection(collection:(Mutable)Collection<String!>!): Unit defined in KotlinClass



无论我做什么,都无法仅使用 Kotlin 代码对其进行编译。

重现这种情况的代码:
//JavaInterface.class
import java.util.Collection;

public interface JavaInterface {
    void setCollection(Collection<String> collection);
}

//JavaBaseClass.class
import java.util.Collection;

public class JavaBaseClass {
    public void setCollection(Collection collection){}
}

//JavaSubClass.class
public class JavaSubClass extends JavaBaseClass implements JavaInterface {}

//KotlinClass.kt
class KotlinClass : JavaSubClass() 

Java 本身没有这个问题。所以我的猜测是这可能与平台类型有关( String! 不是 Any? )。

是否有针对此问题的优雅解决方法,最好不涉及编写 Java 代码?或者这应该在 Kotlin 编译器本身中修复吗?

最佳答案

我还没有详细了解 java 在 JavaSubClass 中的工作方式/原因,即它会产生什么字节码,但从 Kotlin 的角度来看,如果我查看这两种方法的签名,它们的调度会模棱两可。

这:

public void setCollection(Collection collection){}

被视为设置具有泛型类型 Any? 的集合的方法。
任何?是字符串的超集。

如果您类(class)的客户有以下情况:
myCollection = Array<String>()
myInstanceOfKotlinClass.setCollection(myCollection)

应该分派(dispatch)哪种方法?

出于这个原因,我认为这不是 Kotlin 编译器中的错误,而是对一些较松散的 java 泛型类型安全性的改进。显然,java 会选择如何将这两种方法编译到字节码中的同一个类中,如果您知道在上述情况下将选择哪个方法进行分派(dispatch),那么这是一个不错的方法。但我认为你应该能够仅从签名中分辨出哪一个,而不是一些内部知识。

恐怕我正在努力寻找一种解决方法来为您提供该类型的扩展 kotlin 类。因此,如果您想为该 java 类添加更多功能,并且不需要任何额外的实例状态,您可以尝试使用扩展函数吗?
fun JavaSubClass.newFunctionality(){}

感觉就像您使用的第三方代码在使用泛型和继承方面做得很差。不管怎样,如果您需要更改现有功能的行为或拥有新功能的实例状态,我认为您在处理 Java 领域的这种歧义时会遇到困难,因为我认为 Kotlin 不同意它作为一个原则问题。

编辑:

看着java,这个
//JavaSubClass.class
public class JavaSubClass extends JavaBaseClass implements JavaInterface {}

暗示 JavaBaseClass 实现了接口(interface)....

它拓宽了接口(interface)的通用类型。讨厌的类型删除错误迫在眉睫。我的意思是看这个:
import java.util.ArrayList;

public class Main {

    public static void main(String[] args) {
        JavaSubClass sc = new JavaSubClass();
        ArrayList<Integer> myCollection = new ArrayList<>();
        sc.setCollection(myCollection);
    }
}

哎呀。

关于inheritance - 在 Kotlin 中扩展 Java 类时继承的平台声明冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45975121/

相关文章:

clojure - 当您在 Clojure 中扩展 Java 类并定义与该类中的方法同名的方法时,会发生什么?

python - 类方法缺少一个位置参数

javascript - 在类函数中访问 JavaScript 类变量

c++ - 查看对象是什么类

android - 如何使用 DownloadManager 列

java - Kotlin + Dagger 和注入(inject)构造函数?我对此迷失了

android - 在 fragment 中点击OptionsMenu项时不需要的导航

c# - JNBridge可以在linux下使用吗?

c++ - Arduino - 如何使用指针增加(继承的)公共(public)类成员?

scala - 从 Scala 调用 Java : protected constructor