【发布时间】:2020-07-08 15:41:33
【问题描述】:
我想知道,如何在 Kotlin 中将泛型类映射到相同类型的泛型数组。
给定以下课程:
class <T> MyClass(val type : Class<T>) {
fun new() = type.newInstance()
}
我想要类似的东西:
class MyOtherClass {
val map = Map<Class<T>, MyClass<T>>
inline fun <reified T> get() : MyClass<T> {
if(T::class.java in map) {
return map[T::class.java]
} else {
val newInstance = MyClass(T::class.java)
map[T::class.java] = newInstance
return newInstance
}
}
}
但是,这不起作用,因为:
- T 不能在 MyOtherClass 中使用
- 在 MyOtherClass 中将 T 更改为 Any 会引发类型推断错误,需要 Any 但我们有 T
- 更改为 Any 也不起作用
- 更改为确实有效,但会发出警告,“return map[T::class.java]”是未经检查的演员表
我不知道如何以及是否可以这样写,但从逻辑的角度来看,我想实现以下目标:
- 有一个通用管理器类,可以为给定类型执行某些操作(=上面的 MyClass)
- 有另一个类按类型缓存此类管理器类。如果存在给定类型的管理器,则应使用该管理器而不是创建新管理器
- 因此,我想将一个类型映射到同一类型的经理
如前所述,我有一种编写方法,如下所示,但我想避免强制转换警告,因为在我看来它是无效的,因为地图应该告诉编译器获取 X 类型的东西将返回X 类型的 MyClass。
class MyOtherClass {
val map = Map<Class<out Any>, MyClass<out Any>>
inline fun <reified T:Any> get() : MyClass<T> {
if(T::class.java in map) {
return map[T::class.java] as MyClass<T>
} else {
val newInstance = MyClass(T::class.java)
map[T::class.java] = newInstance
return newInstance
}
}
}
感谢大家的帮助!
【问题讨论】:
-
将您的地图更改为
val map = mutableMapOf<Class<*>, MyClass<*>>(),然后以您的方法return map[T::class.java] as MyClass<T>为我工作 -
感谢您的快速回复!你没有收到未经检查的演员表的警告吗?至少这是我得到的,但也许我做的事情与你不同而“*”到底是什么?我只知道 Kotlin 中的 Any 和 Nothing。
-
*是一个通配符,因此您不知道自己在使用什么。未经检查的演员表是一个后果,据我所知,你无法解决 -
是的,警告是合法的,因为它周围不再有编译时类型安全性。您必须确保只存储合理的映射,然后您可以取消警告。你基本上是在告诉工具“我知道我在这里做什么,这是安全的。”
-
谢谢你们!我明天会写一个干净的答案然后关闭它