14-实例化类型参数
11.3.4 实例化类型参数
有些时候,需要访问一个作为参数传递过来的类型。例如,下面是遍历一个树结构,并使用反射来检查节点是否为某个指定类型的例子。
fun <T> TreeNode.findParentOfType(clazz: Class<T>): T? {
var p = parent
while (p != null && !clazz.isInstance(p)) {
p = p.parent
}
@Suppress("UNCHECKED_CAST")
return p as T?
}
虽然上面的代码在逻辑上没有任何问题,但是调用该函数时需要传递一个类文件,而这并不是很方便,实际上我们更希望只是简单地传入一个类型参数即可。为了达到这个目的,内联函数提供了实例化的参数类型,上面的代码可以改写为如下形式。
inline fun <reified T> TreeNode.findParentOfType(): T? {
var p = parent
while (p != null && p !is T) {
p = p.parent
}
return p as T?
}
使用修饰符reified限制的参数类型,可以在内联函数中访问。由于函数是内联的,因此不需要反射,只需要使用诸如!is和as的普通操作符执行即可。
虽然在很多情况下不需要反射,但仍可以在一个实例化的参数类型中使用反射。代码如下。
inline fun <reified T> membersOf() = T::class.members
fun main(s: Array<String>) {
println(membersOf<StringBuilder>().joinToString("\n"))
}
通常,普通函数(未标记为内联)不可以包含reified类型参数。也就是说,一个没有运行时表现的类型,不可以被用作实例化类型参数。