Home Articles

在Kotlin中扩展Java类时,继承的平台声明会发生冲突

Asked
Viewed 1551 times
2

我正在尝试使用Kotlin扩展第三方Java类,但是我得到了这个编译器消息:

继承的平台声明冲突:以下声明具有相同的JVM签名(setCollection(Ljava / util / Collection;)V):fun setCollection(collection:(Mutable)Collection <(raw)Any?>!:在KotlinClass中定义的单位乐趣setCollection(collection:(Mutable)Collection <String!>!):在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编译器本身内修复?

1 Answer

  • 0

    我没有仔细研究Java如何/为什么在JavaSubClass中工作的细节,即它产生的字节码,但从Kotlin的角度来看,如果我看一下这两种方法的签名,它们会有不明确的调度 .

    这个:

    public void setCollection(Collection collection){}
    

    被视为设置具有泛型类型Any的Collection的方法 . 任何?是String的超集 .

    如果您 class 的客户有以下内容:

    myCollection = Array<String>()
    myInstanceOfKotlinClass.setCollection(myCollection)
    

    应该派出哪种方法?

    出于这个原因,我认为这不是Kotlin编译器中的错误,而是对一些更宽松的java泛型类型安全性的改进 . 显然,java可以选择这两个方法如何在字节码中编译到同一个类中,如果您知道在上述情况下将选择哪个方法进行调度,那么这是一个好的方法 . 但我认为你应该只能从签名中分辨哪一个,而不是一些内部知识 .

    我担心我正在努力找到一个解决方法,它会给你一个扩展的kotlin类 . 因此,如果您想要为该java类添加更多功能,并且您不需要任何额外的实例状态,您可以尝试使用扩展功能吗?

    fun JavaSubClass.newFunctionality(){}
    

    感觉就像你使用的第三方代码本身在使用泛型和继承方面做得很差 . 无论哪种方式,如果您需要更改现有功能的行为或具有新功能的实例状态,我认为您在Java领域处理这种模棱两可的问题,因为我认为Kotlin不同意它作为委托人的问题 .

    编辑:

    看看java,这个

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

    意味着JavaBaseClass实现了接口....

    它扩展了接口的泛型类型 . 令人讨厌的类型擦除即将到来 . 我是说看看这个:

    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);
        }
    }
    

    Eeew .

Related