我正在尝试使用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 回答
我没有仔细研究Java如何/为什么在JavaSubClass中工作的细节,即它产生的字节码,但从Kotlin的角度来看,如果我看一下这两种方法的签名,它们会有不明确的调度 .
这个:
被视为设置具有泛型类型Any的Collection的方法 . 任何?是String的超集 .
如果您 class 的客户有以下内容:
应该派出哪种方法?
出于这个原因,我认为这不是Kotlin编译器中的错误,而是对一些更宽松的java泛型类型安全性的改进 . 显然,java可以选择这两个方法如何在字节码中编译到同一个类中,如果您知道在上述情况下将选择哪个方法进行调度,那么这是一个好的方法 . 但我认为你应该只能从签名中分辨哪一个,而不是一些内部知识 .
我担心我正在努力找到一个解决方法,它会给你一个扩展的kotlin类 . 因此,如果您想要为该java类添加更多功能,并且您不需要任何额外的实例状态,您可以尝试使用扩展功能吗?
感觉就像你使用的第三方代码本身在使用泛型和继承方面做得很差 . 无论哪种方式,如果您需要更改现有功能的行为或具有新功能的实例状态,我认为您在Java领域处理这种模棱两可的问题,因为我认为Kotlin不同意它作为委托人的问题 .
编辑:
看看java,这个
意味着JavaBaseClass实现了接口....
它扩展了接口的泛型类型 . 令人讨厌的类型擦除即将到来 . 我是说看看这个:
Eeew .