Sah
Sah

Reputation: 1067

Ignoring certain properties when generating equals(), hashCode(), etc

Let's say I have a data class that has three properties:

data class Product(
    val id: Int,
    val name: String,
    val manufacturer: String)

If I understand correctly, Kotlin will generate equals() and hashCode() using all the three properties, which will be like:

override fun equals(other: Any?): Boolean {
    if (this === other) return true
    if (other == null || javaClass != other.javaClass) return false
    val that = other as Product?
    return id == that.id &&
            name == that!!.name &&
            manufacturer == that.manufacturer
}

override fun hashCode(): Int {
    return Objects.hash(id, name, manufacturer)
}

So what if I don't want id to be used in equals() and hashCode()? Is there a way to tell Kotlin to ignore certain properties when generating these functions? How about toString() and compareTo()?

Upvotes: 2

Views: 4508

Answers (3)

McPringle
McPringle

Reputation: 2129

From the documentation:

Note that the compiler only uses the properties defined inside the primary constructor for the automatically generated functions. To exclude a property from the generated implementations, declare it inside the class body.

Your example has to look like this:

data class Product(
    val name: String,
    val manufacturer: String) {
    val id: Int
}

For more information take a look at: https://kotlinlang.org/docs/reference/data-classes.html#properties-declared-in-the-class-body

Upvotes: 1

mfulton26
mfulton26

Reputation: 31234

A solution that has worked well for me is to separate your metadata from your data. e.g.:

data class Entity<out T>(val id: Int, val data: T)
data class Person(val name: String, val manufacturer: String)

Usage:

val e1 = Entity(1, Person("Mickey", "Disney"))
val e2 = Entity(2, Person("Mickey", "Disney"))
val e3 = Entity(3, Person("Donald", "Disney"))

e1 == e2
// false

e1.data == e2.data
// true

e2.data == e3.data
// false

Upvotes: 2

zsmb13
zsmb13

Reputation: 89578

For data classes, these functions are generated using all the properties that are declared in the primary constructor. From the official documentation:

The compiler automatically derives the following members from all properties declared in the primary constructor:

  • equals()/hashCode() pair,
  • toString() of the form "User(name=John, age=42)",
  • componentN() functions corresponding to the properties in their order of declaration,
  • copy() function (see below).

If you want a property not to be taken into account for their implementation, you'll have to either move it out of the primary constructor, or implement these functions yourself.

More discussion about a similar issue here.

Upvotes: 5

Related Questions