Chr*_*ann 5 inheritance java-interop kotlin
我正在尝试使用 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()
Run Code Online (Sandbox Code Playgroud)
Java本身不存在这个问题。所以我的猜测是这可能与平台类型有关(String!不是Any?)。
是否有一个优雅的解决方法来解决这个问题,并且最好不涉及编写Java代码?或者应该在 Kotlin 编译器本身中修复这个问题?
我还没有研究 java 如何/为什么在 JavaSubClass 中工作的细节,即它会产生什么字节码,但从 Kotlin 的角度来看,如果我查看这两个方法的签名,它们会有不明确的调度。
这:
public void setCollection(Collection collection){}
Run Code Online (Sandbox Code Playgroud)
被视为设置具有泛型类型 Any? 的 Collection 的方法。任何?是 String 的超集。
如果您班级的客户有以下情况:
myCollection = Array<String>()
myInstanceOfKotlinClass.setCollection(myCollection)
Run Code Online (Sandbox Code Playgroud)
应该调度哪个方法?
因此,我认为这并不是 Kotlin 编译器中的 bug,而是对一些较为宽松的 java 泛型类型安全性的改进。显然,java 会选择如何将这两个方法编译成字节码中的同一个类,如果您知道在上述情况下将选择哪个方法进行分派,那么这是一个不错的方法。但我认为单凭签名你就应该能够分辨出是哪一个,而不是一些内部知识。
恐怕我正在努力寻找一种解决方法,为您提供该类型的扩展 kotlin 类。因此,如果您想向该 java 类添加更多功能,并且不需要任何额外的实例状态,您可以尝试使用扩展函数吗?
fun JavaSubClass.newFunctionality(){}
Run Code Online (Sandbox Code Playgroud)
感觉您正在使用的第三方代码本身在使用泛型和继承方面做得很差。不管怎样,如果您需要更改现有功能的行为或为新功能提供实例状态,我认为您必须处理 Java 领域中的这种歧义,因为我认为 Kotlin 原则上不同意这一点。
编辑:
看看java,这个
//JavaSubClass.class
public class JavaSubClass extends JavaBaseClass implements JavaInterface {}
Run Code Online (Sandbox Code Playgroud)
意味着 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);
}
}
Run Code Online (Sandbox Code Playgroud)
哎呀。
| 归档时间: |
|
| 查看次数: |
2053 次 |
| 最近记录: |