代码:
abstract class DataContainer(public val path: String)
val preloaded: MutableMap<Class<out DataContainer>, HashSet<out DataContainer>> = hashMapOf()
我想知道如何让Kotlin意识到第一个out DataContainer
与第二个out DataContainer
的类型相同。
所以代码如:
fun <D: DataContainer> get(clazz: Class<D>): HashSet<D> = preloaded[clazz] as HashSet<D>
不需要as HashSet<D>
(并且不容易出错)。
我是Kotlin的新手,如果我错过了某些内容,请链接文档。
此外,如果重要,此代码将位于object
内。
答案 0 :(得分:1)
我认为你想要的东西在语言水平上是不可行的。
只要你能安全地进行,get
方法中的强制转换并不是那么糟糕。我能够安全地看到的唯一方法是控制put
方法。
如果您强制将D : DataContainer
类型的每个键与Set<D>
类型的键配对,则可以在获取时安全地进行投射。例如,你可以这样:
object DataContainerRegistry {
private val preloaded: MutableMap<Class<out DataContainer>, HashSet<DataContainer>> = hashMapOf()
fun put(dataContainer: DataContainer) {
val set = preloaded.getOrDefault(dataContainer::class.java, HashSet())
set.add(dataContainer)
preloaded[dataContainer::class.java] = set
}
fun <D : DataContainer> get(clazz: Class<D>) = preloaded.getOrDefault(clazz, HashSet()) as Set<D>
}
此方法的局限性是:
DataContainerRegistry
单身人士)可以直接访问preloaded
地图get
方法只返回Set
,而不是可变接口。 通过这种方式,你知道没有人会把preloaded
和其中包含的Set
弄得一团糟,然后你就可以轻松投入。
答案 1 :(得分:0)
部分内容是Java语言基础。
正如您的示例所示,假设您有一组Animal
个对象。您可以将Cat
和Dog
放在那里,但是当涉及到专门提取Cat
时,您必须通过使用强制转换断言它确实是Cat
但是,如果您愿意将集合的特定实例限制为只处理Cat
或Dog
,那么这样可以正常工作。
所以,让我们假设我们有:
abstract class DataContainer(public val path: String)
abstract class CatDataContainer(path: String): DataContainer(path)
abstract class DogDataContainer(path: String): DataContainer(path)
这只是你的DataContainer和两个子类。
如果我们在拥有地图的类上放置一个类型参数,我们可以这样做:
class TypedContainerHolder1<D: DataContainer> {
val preloaded: MutableMap<Class<out D>, HashSet<out D>> = hashMapOf()
fun get(clazz: Class<D>): HashSet<out D>? = preloaded[clazz]
}
val typedContainerHolder1 = TypedContainerHolder1<CatDataContainer>()
此外,我们可以通过将地图限制为相同的键/值对类型来改进。这也使用了Kotlin的代表团。
class TypedContainerHolder2<D: DataContainer> {
inner class PreloadedMap<MapType : D> : Map<Class<out MapType>, HashSet<out MapType>> by hashMapOf()
private val preloaded = PreloadedMap<D>()
fun get(clazz: Class<D>): HashSet<out D>? = preloaded[clazz]
}
val typedContainerHolder2 = TypedContainerHolder2<DogDataContainer>()
没有演员表,一旦你设置了它就会有更多类型的安全性。问题是您的方案是否允许此约束。