Suppose I only want one or two fields to be included in the generated equals and hashCode implementations (or perhaps exclude one or more fields). For a simple class, e.g.:
data class Person(val id: String, val name: String)
Groovy has this:
@EqualsAndHashCode(includes = 'id')
Lombok has this:
@EqualsAndHashCode(of = "id")
What is the idiomatic way of doing this in Kotlin?
data class Person(val id: String) { // at least we can guarantee it is present at access time var name: String by Delegates.notNull() constructor(id: String, name: String): this(id) { this.name = name } }
Just feels wrong though... I don't really want name
to be mutable, and the extra constructor definition is ugly.
Kotlin generates the basic functions that must be overloaded for a good model class, giving us good toString(), hashCode(), and equals() functions. Kotlin also provides some extra functionality in the form of a copy() function, and various componentN() functions, which are important for variable destructuring.
By default, in Kotlin, classes are final and cannot be subclassed. You are only allowed to inherit from abstract classes or classes that are marked with the open keyword. Hence you need to mark the RoundHut class with the open keyword to allow it to be inherited from.
Data Class Limitations They can't be open , abstract , sealed or inner classes. The compiler forbids manually implementing copy() and componentN() methods. Any parent interface or class of a data class must not have a copy() method.
Properties are the variables (to be more precise, member variables) that are declared inside a class but outside the method. Kotlin properties can be declared either as mutable using the “var” keyword or as immutable using the “val” keyword.
I've used this approach.
data class Person(val id: String, val name: String) { override fun equals(other: Person) = EssentialData(this) == EssentialData(other) override fun hashCode() = EssentialData(this).hashCode() override fun toString() = EssentialData(this).toString().replaceFirst("EssentialData", "Person") } private data class EssentialData(val id: String) { constructor(person: Person) : this(id = person.id) }
This approach may be suitable for property exclusion:
class SkipProperty<T>(val property: T) { override fun equals(other: Any?) = true override fun hashCode() = 0 }
SkipProperty.equals
simply returns true, which causes the embeded property
to be skipped in equals
of parent object.
data class Person( val id: String, val name: SkipProperty<String> )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With