如何将数据类型映射到该数据类型的集合

时间:2018-02-24 03:39:45

标签: types kotlin

代码:

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内。

2 个答案:

答案 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>

}

此方法的局限性是:

  1. 我的示例中只有一个班级(DataContainerRegistry单身人士)可以直接访问preloaded地图
  2. get方法只返回Set,而不是可变接口。
  3. 通过这种方式,你知道没有人会把preloaded和其中包含的Set弄得一团糟,然后你就可以轻松投入。

答案 1 :(得分:0)

部分内容是Java语言基础。

正如您的示例所示,假设您有一组Animal个对象。您可以将CatDog放在那里,但是当涉及到专门提取Cat时,您必须通过使用强制转换断言它确实是Cat

但是,如果您愿意将集合的特定实例限制为只处理CatDog,那么这样可以正常工作。

所以,让我们假设我们有:

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>()

没有演员表,一旦你设置了它就会有更多类型的安全性。问题是您的方案是否允许此约束。