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

我想用Kotlin扩展第三方的Java类,但是我得到这个编译器信息:

继承的平台声明冲突:以下声明具有相同的JVM签名(setCollection(Ljava / util / Collection;)V):

  • fun setCollection(collection:(Mutable)Collection <(raw)Any?> !:在KotlinClass中定义的单位

  • fun 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编译器本身中解决?

我没有详细了解Java / Java为什么会在你的JavaSubClass中工作,也就是说它会产生什么字节码,但是从Kotlin的角度来看,如果我看看这两种方法的签名,他们会有模糊的调度。

这个:

 public void setCollection(Collection collection){} 

被看作是一个设置泛型类型Any的方法。 任何? 是String的超集。

如果您的班级的客户有以下情况:

 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。