设置类的所有属性的值
作为示例,我们要设置示例类的所有字符串属性
class TestClass {
val readOnlyProperty: String
get() = "Read only!"
var readWriteString = "asd"
var readWriteInt = 23
var readWriteBackedStringProperty: String = ""
get() = field + '5'
set(value) { field = value + '5' }
var readWriteBackedIntProperty: Int = 0
get() = field + 1
set(value) { field = value - 1 }
var delegatedProperty: Int by TestDelegate()
private var privateProperty = "This should be private"
private class TestDelegate {
private var backingField = 3
operator fun getValue(thisRef: Any?, prop: KProperty<*>): Int {
return backingField
}
operator fun setValue(thisRef: Any?, prop: KProperty<*>, value: Int) {
backingField += value
}
}
}
获取可变属性建立在获取所有属性的基础上,按类型过滤可变属性。我们还需要检查可见性,因为读取私有属性会导致运行时异常。
val instance = TestClass()
TestClass::class.memberProperties
.filter{ prop.visibility == KVisibility.PUBLIC }
.filterIsInstance<KMutableProperty<*>>()
.forEach { prop ->
System.out.println("${prop.name} -> ${prop.get(instance)")
}
要将所有 String
属性设置为 Our Value
,我们还可以按返回类型进行过滤。由于 Kotlin 基于 Java VM,因此 Type Erasure 生效,因此返回 List<String>
等泛型类型的 Properties 将与 List<Any>
相同。可悲的是,反射不是一个金色的子弹,没有明智的方法来避免这种情况,所以你需要注意你的用例。
val instance = TestClass()
TestClass::class.memberProperties
.filter{ prop.visibility == KVisibility.PUBLIC }
// We only want strings
.filter{ it.returnType.isSubtypeOf(String::class.starProjectedType) }
.filterIsInstance<KMutableProperty<*>>()
.forEach { prop ->
// Instead of printing the property we set it to some value
prop.setter.call(instance, "Our Value")
}