给定具体化类型参数 T
,如果该类型是 List
,如何获取列表的项目类型?
我尝试使用 T : Any
重载具体化方法和T : List
还有TItem : Any, TList: List<TItem>
但由于重载冲突,因此无法编译。
编译失败,重载冲突
inline fun <reified T> getRequiredVariable(variableName: String) =
// ... implementation
inline fun <reified TItem, reified TList : List> getRequiredVariable(variableName: String) =
// ... implementation
解决方法尝试失败
inline fun <reified T : Any> getRequiredVariable(variableName: String) =
if (T::class.isSubclassOf(List::class)) {
val tKClass = T::class
val itemType = tKClass.typeParameters[0] // Won't work, even though T is reified, the type parameter apparently is not
val itemClassifier = itemType.createType().classifier
val itemKClass = itemClassifier as KClass<*> // Fails, KTypeParamaterImpl is not KClass<*>
getRequiredListVariable(variableName, itemKClass) as? T
} else {
getRequiredVariable(variableName, T::class)
}
最佳答案
这里的问题是您想要访问类型参数,但是 KClass
/Class
抽象仅提供对类型参数的访问(类本身中声明的内容,而不是在此特定具体化调用站点中传递的实际类型)。
您不应该为此使用该类,但 Type
/KType
反而。有方便typeOf函数在具体化类型上访问它,然后您可以通过 arguments 访问类型参数属性:
val typeArgs = typeOf<T>().arguments
一旦有了这些,您就可以像在现有代码中一样访问它们的类型和该类型的分类器,但这次它将是实际类型参数的类型。
inline fun <reified T : Any> getRequiredVariable(variableName: String) =
if (T::class.isSubclassOf(List::class)) {
val itemTypeProjection = typeOf<T>().arguments[0]
val itemType = itemTypeProjection.type ?: error("Cannot get list item type from List<*>")
val itemKClass = itemType.classifier as? KClass<*> ?: error("The list item type is not denotable in Kotlin")
getRequiredListVariable(variableName, itemKClass) as? T
} else {
getRequiredVariable(variableName, T::class)
}
但是请注意,访问类型参数 0 通常不会为您提供 List
的任何实现类的项类型。 。例如,如果类型为 class MyStringList : List<String>
,它没有类型参数,但它是 List
的子类型。更糟糕的是,它可能有一个与列表元素无关的类型参数,如 class MyWeirdClass<X> : List<String>
中所示。 (使用 X 表示不相关的事情)。为了克服这个问题,您可能需要沿着父类(super class)型的层次结构向上查找 List
的类型。 T
声明中使用的接口(interface)的类型 - 这可能会很痛苦。
关于kotlin - 获取具体化泛型类型的具体化类型参数kclass,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73709189/