如何使用kotlin和refelction迭代嵌套数据类
我有一个名为report的数据类,它本质上是一个变量列表的列表,即嵌套的数据类如何使用kotlin和refelction迭代嵌套数据类,kotlin,reflection,Kotlin,Reflection,我有一个名为report的数据类,它本质上是一个变量列表的列表,即嵌套的数据类 data class report( var list1 : List1, var list2 : List2 ) : Parcelable data class List1 ( var a: Boolean = false, var b: Boolean = false, ) : Parcelable data class List2 ( var c : Boolea
data class report(
var list1 : List1,
var list2 : List2
) : Parcelable
data class List1 (
var a: Boolean = false,
var b: Boolean = false,
) : Parcelable
data class List2 (
var c : Boolean = false,
var d : Boolean = false,
) : Parcelable
使用Kotlin和reflection,我有一个for循环,它迭代顶级数据类,并成功地打印变量的名称。我想迭代每个嵌套类并打印变量名称,但如果不按名称显式引用嵌套类,我就无法知道如何执行该操作。第一个for循环打印正确的数据,而第二个for循环只打印“长度”
在第二个循环中,我感觉“prop”没有被正确地扩展为对嵌套类的引用。我尝试了“report.prop.name”或“report.${prop.name}”之类的方法,但没有成功。我还尝试将report.prop.name分配给一个单独的变量。这是一个我不知道的简单语法问题吗?我确实读过Stack上的其他类似问题,但没有找到解决方案。这可能与没有在适当的时候创建类实例有关吗?问题是,您试图迭代可能不同类型的属性,因此反射无法知道顶层之后是什么类型
report::class.declaredMemberProperties
返回包含KMutableProperty1
对象的集合。无法派生KMutableProperty1
的泛型类型,因为泛型会被擦除,因此可能是任何类型。当然,您知道它们是KMutableProperty1
和KMutableProperty1
,但是您在编译时使用泛型来查看它。反射必须在运行时动态执行,而不使用泛型,因此在使用反射时,您只知道类型为KMutableProperty1
我相信这意味着无法动态循环您所描述的属性,因为属性类型在运行时是未知的。唯一的方法是显式地声明每个属性的类型,但这有点违背了这一点:
fun <T : Any> KClass<T>.printPropertyNames(): Unit {
for (prop in declaredMemberProperties) {
println("$this: ${prop.name}")
}
}
fun main() {
Report::class.printPropertyNames()
for (prop in Report::class.declaredMemberProperties) {
when (prop.name) {
"list1" -> List1::class.printPropertyNames()
"list2" -> List2::class.printPropertyNames()
}
}
}
但是,如果您只想查看对象中的内容,可以使用数据类的默认toString()
行为:
println(Report(List1(true, false), List2(false, true)))
输出:
class Report: list1
class Report: list2
class List1: a
class List1: b
class List2: c
class List2: d
Report(list1=List1(a=true, b=false), list2=List2(c=false, d=true))
问题是,您试图迭代可能不同类型的属性,因此反射无法知道顶级之后的类型是什么
report::class.declaredMemberProperties
返回包含KMutableProperty1
对象的集合。无法派生KMutableProperty1
的泛型类型,因为泛型会被擦除,因此可能是任何类型。当然,您知道它们是KMutableProperty1
和KMutableProperty1
,但是您在编译时使用泛型来查看它。反射必须在运行时动态执行,而不使用泛型,因此在使用反射时,您只知道类型为KMutableProperty1
我相信这意味着无法动态循环您所描述的属性,因为属性类型在运行时是未知的。唯一的方法是显式地声明每个属性的类型,但这有点违背了这一点:
fun <T : Any> KClass<T>.printPropertyNames(): Unit {
for (prop in declaredMemberProperties) {
println("$this: ${prop.name}")
}
}
fun main() {
Report::class.printPropertyNames()
for (prop in Report::class.declaredMemberProperties) {
when (prop.name) {
"list1" -> List1::class.printPropertyNames()
"list2" -> List2::class.printPropertyNames()
}
}
}
但是,如果您只想查看对象中的内容,可以使用数据类的默认toString()
行为:
println(Report(List1(true, false), List2(false, true)))
输出:
class Report: list1
class Report: list2
class List1: a
class List1: b
class List2: c
class List2: d
Report(list1=List1(a=true, b=false), list2=List2(c=false, d=true))
所以我用一个函数和一个for循环做到了这一点,如下所示:
fun <T> printProperty(instance: T, prop: KProperty1<T, *>): Any? {
println("${prop.name} = ${prop.get(instance)}")
return prop.get(instance)
}
for (rep in MyReport::class.memberProperties) {
val reportProperty = MyReport::class.memberProperties.single{ it.name == rep.name}
val reportInstance = printProperty(report, reportProperty)
for (subRep in reportInstance!!::class.memberProperties) {
println("${subRep.name} = ${subRep.getter.call(reportInstance)}")
}
}
fun printProperty(实例:T,属性:KProperty1):有吗?{
println(${prop.name}=${prop.get(实例)}”)
返回prop.get(实例)
}
for(MyReport::class.memberProperties中的代表){
val reportProperty=MyReport::class.memberProperties.single{it.name==rep.name}
val reportInstance=printProperty(报告,reportProperty)
对于(reportInstance!!::class.memberProperties中的子代表){
println(${subRep.name}=${subRep.getter.call(reportInstance)}”)
}
}
我不知道为什么,但我不能在第二次for循环中再次使用我的函数-相反,我必须使用getter.call来获得我想要的值。所以我用一个函数和一个for循环做到了这一点,就像这样:
fun <T> printProperty(instance: T, prop: KProperty1<T, *>): Any? {
println("${prop.name} = ${prop.get(instance)}")
return prop.get(instance)
}
for (rep in MyReport::class.memberProperties) {
val reportProperty = MyReport::class.memberProperties.single{ it.name == rep.name}
val reportInstance = printProperty(report, reportProperty)
for (subRep in reportInstance!!::class.memberProperties) {
println("${subRep.name} = ${subRep.getter.call(reportInstance)}")
}
}
fun printProperty(实例:T,属性:KProperty1):有吗?{
println(${prop.name}=${prop.get(实例)}”)
返回prop.get(实例)
}
for(MyReport::class.memberProperties中的代表){
val reportProperty=MyReport::class.memberProperties.single{it.name==rep.name}
val reportInstance=printProperty(报告,reportProperty)
对于(reportInstance!!::class.memberProperties中的子代表){
println(${subRep.name}=${subRep.getter.call(reportInstance)}”)
}
}
我不知道为什么,但我不能在second for循环中再次使用我的函数-相反,我必须使用getter.call来获得我想要的值。谢谢Adam。这是否解释了为什么我不能使用抽象函数引用嵌套类?类似于:
println(report.prop.name)
问题在于prop
是KMutableProperty1
,因此subop
表示KMultableProperty1
类的属性,而不是List1
、List2
等。谢谢Adam。这是否解释了为什么我不能使用抽象函数引用嵌套类?类似于:println(report.prop.name)
问题在于prop
是KMutableProperty1
,因此subop
表示KMultableProperty1
类的属性,而不是List1
,List2
,等等。