Java Kotlin-扩展泛型类并返回子类型时出现问题
我有以下情况:Java Kotlin-扩展泛型类并返回子类型时出现问题,java,kotlin,generics,hierarchy,Java,Kotlin,Generics,Hierarchy,我有以下情况: 抽象泛型类 抽象类K{ 抽象趣味绑定(itemModel:T) } 从K A类:K类{ 覆盖趣味绑定(itemModel:ModelA){ //…做任何事 } } B类:K{ 覆盖趣味绑定(itemModel:ModelB){ //…做任何事 } } 另一个类,这是一个工厂,它根据某个参数返回K的子类型: 类工厂{ 伴星{ const val TYPE_A:Int=0 const val TYPE_B:Int=1 趣味创作(类型:Int):K{ 返回时间(类型){
- 抽象泛型类
抽象类K{
抽象趣味绑定(itemModel:T)
}
- 从
K
A类:K类{
覆盖趣味绑定(itemModel:ModelA){
//…做任何事
}
}
B类:K{
覆盖趣味绑定(itemModel:ModelB){
//…做任何事
}
}
- 另一个类,这是一个工厂,它根据某个参数返回K的子类型:
类工厂{
伴星{
const val TYPE_A:Int=0
const val TYPE_B:Int=1
趣味创作(类型:Int):K{
返回时间(类型){
键入A->A()
类型_B->B()
}
}
}
}
此时,我在Factory.create
方法的return-type部分得到一个错误,它说:“类Kcreate
方法中返回K的子类型,这是唯一重要的事情,而不是泛型的特定类型
这在Java中是可能的。科特林的正确方式是什么 这里有很多地方需要改进(根据评论更新)
- 如果参数不是
或类型A
类型B
- 将*添加到参数化的K返回类型
fun create(type: Int): K<*> {
return when (type) {
TYPE_A -> A()
TYPE_B -> B()
else -> throw IllegalStateException("useful message")
}
}
fun create(类型:Int):K{
返回时间(类型){
键入A->A()
类型_B->B()
else->抛出IllegalStateException(“有用消息”)
}
}
这里有很多地方需要改进(根据评论更新)
- 如果参数不是
或类型A
类型B
- 将*添加到参数化的K返回类型
fun create(type: Int): K<*> {
return when (type) {
TYPE_A -> A()
TYPE_B -> B()
else -> throw IllegalStateException("useful message")
}
}
fun create(类型:Int):K{
返回时间(类型){
键入A->A()
类型_B->B()
else->抛出IllegalStateException(“有用消息”)
}
}
问题在于K
不是一个完整的类型,就像Java中不能返回列表一样-必须返回列表。因此,您需要说明这将返回一个K
(或一些其他类型的绑定)
但是,现在您还有一个类型差异问题,因为K
不是K
的子类型,除非K
的声明是K
,但是您的bind
方法在in
位置有T
,所以这是不可能的。这是有道理的,因为如果我给你一个调用create
的结果,你就无法知道你可以传递给bind
什么类型的东西,所以它没有那么有用
如前一个回复中所述,您可以创建returnK
,这将进行编译,但我不确定这是否有用,因为您必须知道实际的类型才能调用bind
——也就是说,您必须强制转换任何create
返回,在这种情况下,您可能只需构造特定于类型的首先。问题是K
不是一个完整的类型,就像Java中不能返回列表一样-必须返回列表。因此,您需要说明这将返回一个K
(或一些其他类型的绑定)
但是,现在您还有一个类型差异问题,因为K
不是K
的子类型,除非K
的声明是K
,但是您的bind
方法在in
位置有T
,所以这是不可能的。这是有道理的,因为如果我给你一个调用create
的结果,你就无法知道你可以传递给bind
什么类型的东西,所以它没有那么有用
如前一个回复中所述,您可以创建returnK
,这将进行编译,但我不确定这是否有用,因为您必须知道实际的类型才能调用bind
——也就是说,您必须强制转换任何create
返回,在这种情况下,您可能只需构造特定于类型的首先。您可以通过返回K
来编译它,但是您将无法对返回的实例执行太多操作。在Java中,可以通过忽略编译器警告来处理原始类型,并在开始尝试调用返回对象上的方法时冒ClassCastException的风险,但是为什么要使用泛型呢
相反,您可以使用具体化类型,以便调用方可以传递生成的实例可以处理的类型,而不是某个数字:
@Suppress("UNCHECKED_CAST")
inline fun <reified T> create(): K<T> {
return when (T::class) {
ModelA::class -> A()
ModelB::class -> B()
else -> error("unsupported type")
} as K<T>
}
@Suppress(“未选中的\u CAST”)
inline fun create():K{
返回时间(T::class){
ModelA::class->A()
ModelB::class->B()
else->错误(“不支持的类型”)
}作为K
}
您可以通过返回K
来编译它,但是您将无法对返回的实例执行太多操作。在Java中,可以通过忽略编译器警告来处理原始类型,并在开始尝试调用返回对象上的方法时冒ClassCastException的风险,但是为什么要使用泛型呢
相反,您可以使用具体化类型,以便调用方可以传递生成的实例可以处理的类型,而不是某个数字:
@Suppress("UNCHECKED_CAST")
inline fun <reified T> create(): K<T> {
return when (T::class) {
ModelA::class -> A()
ModelB::class -> B()
else -> error("unsupported type")
} as K<T>
}
@Suppress(“未选中的\u CAST”)
inline fun create():K{
返回时间(T::class){
ModelA::class->A()
ModelB::class->B()
else->错误(“不支持的类型”)
}作为K
}