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



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

继承的平台声明冲突:以下声明 相同的JVM签名(setCollection(ljava/util/collection;)v):

  • fun setCollection(集合:(Mutable)Collection<(raw)noce>!:在Kotlinclass中定义的单位

  • fun setCollection(集合:(mutable)收集< string!>!):kotlinclass中定义的单位

无论我做什么

复制情况的代码:

//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){}

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

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

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

应该派遣哪种方法?

因此,我认为这不是Kotlin编译器中的错误,而是一些宽松的Java通用类型安全性的改进。显然,Java可以选择这两种方法如何在字节码中汇编为同一类,如果您知道在上述情况下将选择哪种方法进行调度,这是可以的。但是我认为您应该能够单独从签名中分辨出哪一个,而不是某些内部知识。

我恐怕我正在努力寻找解决方法,这将为您提供这种类型的Kotlin类。因此,如果您想在该Java类中添加更多功能,并且不需要任何额外的实例状态,则可以尝试使用扩展功能?

fun JavaSubClass.newFunctionality(){}

感觉就像您正在使用的第三方代码自己在使用仿制药和继承方面做得很差。但是,无论哪种方式,如果您需要更改现有功能的行为或具有新功能的实例状态,我认为您坚持在Java Land中处理这种歧义,因为Kotlin不同意它,因为我认为Kotlin不同意。

编辑:

看着爪哇,这个

//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。

最新更新