有没有办法有效地比较任意对象的字段



目前,如果我需要按特定字段比较对象,我实现 DiffEqual 接口

interface DiffEquals<T> {
fun isItemSame(other: Any?): Boolean
fun isContentSame(other: Any?): Boolean
}

某个对象

data class Book(
val title: String, val amount: String, var isSelected: Boolean = false
) : DiffEquals {
override fun isItemSame(other: Any?): Boolean {
if (other != null && other is Book) {
if (title != other.title) {
return false
}
return true
} else {
return false
}
}
override fun isContentSame(other: Any?): Boolean {
other as Book
if (amount != other.amount) return false
if (isSelected != other.isSelected) return false
return true
}
}

我不喜欢这种方法,因为它需要大量的虚拟代码。我尝试制作像 Id1、Id2、Id3、可变 1、可变 2、可变 3 等注释,但这需要资源成本,因此我不得不回滚到上面的接口。 如何实现比较指定字段的通用比较机制?(不是标准的等于不适合,因为更复杂的对象具有不断变化的字段,但对于相等并不重要,覆盖等于会在虚拟代码中产生相同的问题,在大多数情况下,我需要完全等于(

您可以创建inlineequalsBy函数:

@PublishedApi
@Suppress("UNCHECKED_CAST")
internal inline fun <T> T.eqlBy(other: Any?, prop1: T.() -> Any?): Boolean = prop1() == (other as T).prop1()
inline fun <reified T> T.equalsBy(other: Any?, prop1: T.() -> Any?): Boolean =
other is T && eqlBy(other, prop1)
inline fun <reified T> T.equalsBy(other: Any?, prop1: T.() -> Any?, prop2: T.() -> Any?): Boolean =
equalsBy(other, prop1) && eqlBy(other, prop2)
inline fun <reified T> T.equalsBy(other: Any?, prop1: T.() -> Any?, prop2: T.() -> Any?, prop3: T.() -> Any?): Boolean =
equalsBy(other, prop1, prop2) && eqlBy(other, prop3)

并像这样使用它们:

data class Book(
val title: String, val amount: String, var isSelected: Boolean = false
) : DiffEquals<Book> {
override fun isItemSame(other: Book) = equalsBy(other) { title }
override fun isContentSame(other: Book) = equalsBy(other, { amount }, { isSelected })
}

使用 varargs 对@Bananon答案略有警告

inline fun <reified T> T.equalTo(other: Any?, vararg properties: T.() -> Any?): Boolean {
if (other !is T) return false
properties.forEach {
if (it.invoke(this) != it.invoke(other)) {
return false
}
}
return true
}

最新更新