具体化类型参数
有时我们需要访问传入给参数的类型:
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
}
在这里,我们沿着继承树,使用反射判断一个节点是不是特定类型。这没什么不妥,但是实现过程不优雅。
myTree.findParentOfType(MyTreeNodeType::class.java)
我们真正想要的仅仅是简单的传递一个类型给这个函数,比如:
myTree.findParentOfType<MyTreeNodeType>()
为了实现这个功能,inline函数支持具体化类型参数,所以我们可以这样写:
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都可以使用。同样的,我们可以按照上述的方式调用这个方法。
myTree.findParentOfType<MyTreeNodeType>()
尽管反射在很多情况下不是必要的,我们依然可以在使用具体化参数的地方使用反射。
inline fun <reified T> membersOf() = T::class.members
fun main(s: Array<String>) {
println(membersOf<StringBuilder>().joinToString("\n"))
}
正常 的函数(未被标记为inline)不能使用具体化参数。不具备运行时展现形式(比如一个非reified的类型参数或虚构的类型比如Nothing)的类型不能被用作具体化类型参数表达式。