Я не уверен, получу ли я то, чего вы действительно хотите достичь. Не забывайте, что генерики стираются во время выполнения, так что в конце вы просто получите 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)
}
И если тип не выводится из значения, вы все равно можете использовать вышеприведенное для создания решения, которое, вероятно, соответствует вашим потребностям.