我想动态遍历kotlin中一个类的所有字段。目的是通过连接所有字段将类对象转换为TSV。由于会有很多子类,所以动态地这样做会很好。经过一番调查,我在下面找到了一个解决方案。它确实起了作用,但字段的顺序与每个字段的声明顺序不一致。
我认为注释可以工作,但不确定如何工作。知道吗?谢谢
abstract class BaseModel {
fun toTSV(): String {
return this::class.memberProperties.map {
it.getter.call(this).toString()
}.joinToString("t")
}
}
class Model (
val model_id: String,
val name: String,
val version: Int,
val desc: String
) : BaseModel()
fun main(args : Array<String>) {
val model = Model(
model_id = "mid",
name = "model name",
version = 1,
desc = "some desc"
)
println(model.toTSV())
}
上面的代码产生:
some_desc mid model_name 1
但我期待:
mid model_name 1 some_desc
就像类中字段的顺序一样。
使用泛型和扩展属性,我们可以像一样实现这一点
val <T> T.fields: List<String>
get() {
return this!!::class.java.declaredFields.map { it.name }
}
val <T> T.fieldsString: String
get() {
return this!!::class.java.declaredFields.map { it.name }.joinToString(", ")
}
fun toTSV2(): String {
val name2value = this::class.memberProperties.map {
it.name to it.getter.call(this).toString()
}.toMap()
return this!!::class.java.declaredFields.map {
name2value[it.name] }.joinToString("t")
}
我建议您在每个模型上覆盖toString,以在每个字段中获得制表符分隔的值:(
class MyModel {
var id: Long = 0L
...
override fun toString(): String {
val sb = StringBuilder()
sb.append("class MyModel {n")
sb.append(" id: ").append(toIndentedString(id)).append("n")
sb.append("n}")
return sb.toString()
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private fun toIndentedString(o: Any?): String {
return o?.toString()?.replace("n", "n ") ?: "null"
}
}
这对我每次都有效。
好的,结合Brandon的回答,我终于得到了这个。成功了:
fun toTSV2(): String {
val name2value = this::class.memberProperties.map {
it.name to it.getter.call(this).toString()
}.toMap()
return this!!::class.java.declaredFields.map {
name2value[it.name] }.joinToString("t")
}