我想比较数据类的多个实例之间的值,以便知道哪个值发生了变化:
data class A(val name : String)
val firstA = A("hello")
val secondA = A("you")
if (secondA.name.changed(firstA)) {
// Do something
}
我可以以某种方式访问.name
的属性函数并在另一个目标值(在此示例中在firstA上)上执行它而不显式定义它吗?
代表可以在这里提供帮助,或者我如何在有反射的情况下解决这个问题?
答案 0 :(得分:3)
我找到了一种不使用反射的方法:
interface DiffValue<T> {
val old : T?
}
fun <T,R> T.changed(memberAccess : T.() -> R) : Boolean {
if (this is DiffValue<*>) {
val old = this.old as? T
if (old != null) {
val currentValue = with(this, memberAccess)
val previousValue = with(old, memberAccess)
return currentValue != previousValue
}
}
return true
}
这就是你如何使用它:
data class A(val val name: String, override val old : A? = null)
val firstA = A("hello")
val secondA = A("you", firstA)
if (secondA.changed {name}) {
// Do something
}
这是基于lambda literals with receivers的概念,它允许Kotlin构建强大的构建器和DSL。
注意:DiffValue
界面是可选的,仅用于使值更容易保持在一起并避免changed
中的其他参数。
答案 1 :(得分:2)
使用Kotlin反射库,您可以使用memberProperties
并按不同值过滤
import java.util.*
import kotlin.reflect.full.memberProperties
data class Example(val a: Int, val b:Long, val c: String)
fun main(args: Array<String>) {
val start = Example(1,2, "A")
val end = Example(1,4, "B")
val differentFields = Example::class.memberProperties.filter {
val startValue = it.get(start)
val endValue = it.get(end)
!Objects.equals(startValue, endValue)
}
differentFields.forEach {
println(it.name)
}
}
输出
b
c
您需要明确地检查每个方法(或将它们存储在列表中并迭代它们)
import java.util.*
data class Example(val a: Int, val b:Long, val c: String) {
fun getChanged(other: Example): List<String> {
val ret: MutableList<String> = mutableListOf()
if (!Objects.equals(a, other.a)) ret.add("a")
if (!Objects.equals(b, other.b)) ret.add("b")
if (!Objects.equals(c, other.c)) ret.add("c")
return ret
}
}
fun main(args: Array<String>) {
val start = Example(1,2, "A")
val end = Example(1,4, "B")
println(start.getChanged(end))
}
import java.util.*
data class Example(val a: Int, val b:Long, val c: String) {
data class Field(val function: (Example) -> Any?, val name: String)
val fields: List<Field> = listOf(
Field({ it.a }, "a"),
Field({ it.b }, "b"),
Field({ it.c }, "c")
)
fun getChanged(other: Example): List<String> {
return fields.filter {
!Objects.equals(it.function(this), it.function(other))
}.map { it.name }
}
}
fun main(args: Array<String>) {
val start = Example(1,2, "A")
val end = Example(1,4, "B")
println(start.getChanged(end))
}