如果您只有一个KClass对象,就可以调用带有类型化参数的乐趣吗?

时间:2019-03-28 14:12:51

标签: generics kotlin kotlin-reified-type-parameters

一个人只能将带有内联函数的类型化参数使用。因此,如果我要为类提供这样的参数,则需要这样的技巧:

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

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

例如杰克逊·科特林Extensions.kt。实际上,这不是一个很好的例子,因为未修饰的等价物都是一线的,但情况并非总是如此-然后您最终将reified-type-parameter方法的实现打包到代码中。

2 个答案:

答案 0 :(得分:0)

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

您可以做一些技巧..与伴侣类一样,但是根本不需要KClass<T>。提供T通用参数的其他任何方法都可以工作以及reified类型的信息

PS:反射也无法可靠地帮助您,因为内联函数在运行时实际上并不存在,如其修饰符inline

所述

答案 1 :(得分:0)

除非我丢失了某些内容,否则在T函数中使用reified T可以执行的所有操作 都可以转换为KClass的用法: x is T变成clazz.isInstance(x)x as T变成clazz.cast(x),对具有确定类型参数的其他函数的调用将进行递归转换,依此类推。由于该函数必须是内联的,因此它使用的所有API在呼叫站点上可见,因此可以在此处进行翻译。

据我所知,并没有自动的方法进行翻译。