在 Kotlin 中扩展 Java class 时继承的平台声明发生冲突
Inherited platform declarations clash when extending a Java class in Kotlin
我正在尝试使用 Kotlin 扩展第三方 Java class,但我收到此编译器消息:
Inherited platform declarations clash: The following declarations have
the same JVM signature (setCollection(Ljava/util/Collection;)V):
fun setCollection(collection:(Mutable)Collection<(raw)Any?>!: Unit defined in KotlinClass
fun setCollection(collection:(Mutable)Collection<String!>!): Unit defined in 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 编译器本身中解决这个问题?
我没有查看 how/why 的细节 java 在你的 Java 子类中工作,即它产生的字节码是什么,但是从 Kotlin 的角度来看,如果我看这两个方法的签名,他们会有不明确的分派。
这个:
public void setCollection(Collection collection){}
是否被视为设置具有通用类型 Any 的 Collection 的方法?。
任何?是字符串的超集。
如果您 class 的客户有以下情况:
myCollection = Array<String>()
myInstanceOfKotlinClass.setCollection(myCollection)
应该调度哪个方法?
出于这个原因,我认为这不是 Kotlin 编译器中的错误,而是对一些更宽松的 java 泛型类型安全性的改进。显然 java 选择了如何将这两种方法编译成相同的 class 字节码,如果您知道在上述情况下将选择哪个方法进行分派,那么这是一个不错的方法。但我认为你应该能够仅从签名中分辨出是哪一个,而不是一些内部知识。
恐怕我正在努力寻找一种解决方法来为您提供该类型的扩展 kotlin class。因此,如果您想向 java class 添加更多功能,并且不需要任何额外的实例状态,您可以尝试使用扩展功能吗?
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);
}
}
哎哟。
我正在尝试使用 Kotlin 扩展第三方 Java class,但我收到此编译器消息:
Inherited platform declarations clash: The following declarations have the same JVM signature (setCollection(Ljava/util/Collection;)V):
fun setCollection(collection:(Mutable)Collection<(raw)Any?>!: Unit defined in KotlinClass
fun setCollection(collection:(Mutable)Collection<String!>!): Unit defined in 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 编译器本身中解决这个问题?
我没有查看 how/why 的细节 java 在你的 Java 子类中工作,即它产生的字节码是什么,但是从 Kotlin 的角度来看,如果我看这两个方法的签名,他们会有不明确的分派。
这个:
public void setCollection(Collection collection){}
是否被视为设置具有通用类型 Any 的 Collection 的方法?。 任何?是字符串的超集。
如果您 class 的客户有以下情况:
myCollection = Array<String>()
myInstanceOfKotlinClass.setCollection(myCollection)
应该调度哪个方法?
出于这个原因,我认为这不是 Kotlin 编译器中的错误,而是对一些更宽松的 java 泛型类型安全性的改进。显然 java 选择了如何将这两种方法编译成相同的 class 字节码,如果您知道在上述情况下将选择哪个方法进行分派,那么这是一个不错的方法。但我认为你应该能够仅从签名中分辨出是哪一个,而不是一些内部知识。
恐怕我正在努力寻找一种解决方法来为您提供该类型的扩展 kotlin class。因此,如果您想向 java class 添加更多功能,并且不需要任何额外的实例状态,您可以尝试使用扩展功能吗?
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);
}
}
哎哟。