反射
- 反射
- 类引用
- 函数引用
- 例子:函数组合
- 属性引用
- 与java反射调用
- 构造函数引用
反射
反射是一系列语言和库的特性,允许在运行是获取你代码结构。Kotlin把函数和属性作为语言的头等类,而且反射他们和使用函数时编程或者响应式编程风格很像。
类引用
最基本的反射特性就是得到运行时的类引用。要获取引用并使之成为静态类可以使用字面类语法:
//类引用
fun getTestClasses(){
val c=TestUser::class
//获取属性名称
for (name in c.memberProperties){
println("TestUser is property is $name")
}
//获取扩展属性
val extensionProperty=c.memberExtensionProperties
for (extension in extensionProperty){
println("extensionProperty is $extension")
}
}
引用是一种KClass类型的值。你可以使用KClass.properties
和KClass.extensionProperties
获取类和父类的所有属性引用的列表
函数引用
当有一个像下面这样的函数声明时:
//反射 函数引用
fun isOdd(x:Int)=x%2!=0
我们可以通过isOdd(5)
轻松调用,同样我们也可以把它作为一个值传递给其他函数,我们可以使用::
操作符
这里::isOdd
是一个函数类型的值(Int)->Boolean
注意现在::
操作符右边不能用于重载函数。将来,我们计划提供一个语法明确参数类型来使用明确的重载函数。
如果需要使用一系列类或者扩展函数,必须是是需合格的,并且结果是扩展函数类型。比如:
String::toCharArray
就带来一个String:String.()->CharArray
类型的扩展函数。
//这个看不懂 什么意思,为什么能成立
fun <A,B,C> compose(f:(B)->C, g:(A)->B):(A)->C{
return {x->f(g(x))}
}
fun testRelfFun(){
fun length(s:String)=s.length
val oddLegth= compose(::isOdd,::length)
// fun <T> ts= compose<String,Int,Boolean>(isOdd(T),length(T))
val testData= listOf("a","ab","cd","abc","abcd")
println(testData.filter(oddLegth))
}
属性引用
在kotlin中访问顶级类的属性,我们也可以使用::
操作符:
//反射的属性引用
var x=1
fun getTestProperty(){
println(::x.get())
::x.set(2)
println(x)
}
::x
表达式评估为KProperty<Int>
类型的属性,它允许我们使用get()
读它的值或者使用名字取回它的属性。
data class TestProperty(var name:String,var age:Int)
fun getTestProperty1(){
val testProperty=TestProperty("cui",29)
val testProperty1=TestProperty::name
val testProperty2=TestProperty::age
testProperty1.set(testProperty,"wyc")
testProperty2.set(testProperty,27)
println("testProperty is $testProperty,${testProperty1.get(testProperty)},${testProperty2.get(testProperty)}")
}
输出结果
testProperty is TestProperty(name=wyc, age=27),wyc,27
对于扩展属性:
//反射 扩展函数
val String.lastD:Char
get() = this[length-1]
fun testRefEx(){
println(String::lastD.get("wyc"))
}
输出
c
与Java反射调用
在Java平台上,标准库包括反射类的扩展,提供了带Java反射对象的映射。
import kotlin.reflect.jvm.*
class A(val p: Int)
fun main(args: Array<String>) {
println(A::p.javaGetter) // prints "public final int A.getP()"
println(A::p.javaField) // prints "private final int A.p"
}
构造函数的引用
构造函数可以像方法或属性那样引用。只需要使用::
操作符并加上类名。下面的函数是一个没有参数并且返回类型是Test
(Class)
//构造函数的引用
class Test
fun testRelFun(function: () -> Test){
val x:Test= Test()
}
fun testConstruRel(){
println(testRelFun(::Test))
}