設定類的所有屬性的值
作為示例,我們要設定示例類的所有字串屬性
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")
}