如果您只有一个 KClass 对象,则使用化类型参数调用乐趣?



只能将化类型参数与内联函数一起使用。因此,如果我想要一个类的参数,我需要这样的技巧:

class Foo<T : Any>(private val clazz: KClass<T>) {
companion object {
inline fun <reified T: Any> create() = Foo(T::class)
}
}

然后,我可以像这样创建Foo实例:

val foo = Foo.create<Bar>()

Foo我可以访问clazz但我的问题是,当我需要调用需要化类型参数的方法时,我可以使用clazz吗?

例如,在Foo中,我想添加这样的方法:

fun print(list: List<Alpha>) {
list.filterIsInstance<T>().forEach { print(it) }
}

但据我所知,没有办法从clazz到我可以在这里用作类型参数的东西。

是的,我知道有一种filterIsInstance需要Class,所以我可以做到:

list.filterIsInstance(clazz.java).forEach { print(it) }

但是,许多库包含提供两种形式(显式类参数和化类型参数)的方法。

例如 Jackson Kotlin Extensions.kt。实际上,这并不是一个很好的例子,因为非化等价物都是单行代码,但情况并非总是如此 - 然后您最终会将化类型参数方法的实现解压缩到代码中。

不,因为这些函数是inline的,所以它们在编译时内联 并且类或 KClass 在运行时使用反射

你可以做一些技巧......就像伴侣类一样,但这根本不需要KClass<T>..任何其他提供T泛型参数的东西对于reified类型信息同样有效

。PS:反射也无法可靠地帮助您,因为内联函数在运行时并不真正存在,正如它们的修饰符inline所解释的那样

除非我遗漏了什么,否则您可以在具有reified T的函数中使用T所做的一切都可以转换为KClass的使用:例如x is T变得clazz.isInstance(x)x as T变得clazz.cast(x),具有化类型参数的其他函数的调用被递归翻译,等等。由于该函数必须是内联的,因此它使用的所有 API 在调用站点上都是可见的,因此可以在那里进行翻译。

但据我所知,没有自动的方法可以进行这种翻译。

最新更新