我不太确定我是否得到了您真正想要完成的任务。不要忘记泛型在运行时会被删除,所以最后你只会有一个Map<KClass<*>, Any>(更准确地说是:Map<Any, Any>)。尽管如此,可能最简单的方法就是坚持你已经知道的。您已经展示了一种便捷方法 (to) 来创建 Pair,然后将其传递给 mapOf,那么为什么不使用符合您要求的新函数,例如
inline fun <reified T : Any> typedPair(value : T) = Pair(T::class, value)
所以你可以使用:
mapOf(
typedPair(10), // adds Int::class as key with 10 as value
typedPair<Short>(1) // adds Short::class as key with 1 as value
typedPair<Number>(2) // adds Number::class as key with 2 as value
)
当然,这样您仍然可以将任何其他星座添加到该地图中。如果你想克服这个问题,你还有一些不同的选择:
创建一个额外的typedMapOf 函数怎么样,例如:
fun typedMapOf(vararg values : Any) = values.associateBy { it::class }
使用它可能如下所示:
typedMapOf(10, "string", 1.toShort())
但是你可能很难添加Number::class ;-)
您还可以将上述两种变体混合为:
data class MyTypedPair<T : Any>(val type : KClass<T>, val value : T)
inline fun <reified T : Any> typedPair(value : T) = MyTypedPair(T::class, value)
fun typedMapOf(vararg values : MyTypedPair<*>) = values.associateBy({it.type}) { it.value }
这基本上迫使您提供专门的类型来创建该类型化的地图。
我还有一些其他的变体......你也可以有一个只支持最小功能集的包装器:
class MyValues {
private val backedMap = mutableMapOf<KClass<*>, Any>()
fun <T : Any> put(value : T) = backedMap.put(value::class, value)
operator fun <T : Any> get(key : KClass<T>) = backedMap[key]
}
用法与Map 略有不同,但仍然非常简单:
MyValues().apply {
put(10)
put<Short>(1)
}
如果类型不能从值派生,那么您仍然可以使用上述方法来构建可能满足您需求的解决方案。