Reputation: 4607
Currently, if I need to compare objects by the specific fields I Implement DiffEqual interface
interface DiffEquals<T> {
fun isItemSame(other: Any?): Boolean
fun isContentSame(other: Any?): Boolean
}
some object
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
}
}
I don't like that approach as it requires a lot of dummy code. I tried to make annotations like Id1, Id2, Id3, Mutable1, Mutable2, Mutable3 and so on, but it was resource costly, thus I had to rollback to interface above. How can one implement a generic comparison mechanism which compares specified fields? (not standard equals does not fit as more complex objects have fields which constantly changes, but are not important for equality, overriding equals creates same problems with dummy code and in most cases, I need full equals to)
Upvotes: 1
Views: 94
Reputation: 4607
slight wariation of @Bananon answer using varargs
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
}
Upvotes: 0
Reputation: 2492
You can create inline
equalsBy
functions:
@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)
And use them like this:
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 })
}
Upvotes: 1