Data classes: equality, hashing and printing for free
Most classes in a real codebase exist only to hold values: a user, an order line, a coordinate. In Java you would hand-write equals, hashCode and toString for each one. In Kotlin you put the word data in front of the class and the compiler generates all three from the properties declared in the primary constructor.
class PlainPoint(val x: Int, val y: Int)
data class Point(val x: Int, val y: Int)
fun main() {
val a = PlainPoint(1, 2)
val b = PlainPoint(1, 2)
println(a == b) // compares references
val p = Point(1, 2)
val q = Point(1, 2)
println(p == q) // compares x and y
println(p) // generated toString
println(p.hashCode() == q.hashCode())
println(setOf(p, q).size)
}false
true
Point(x=1, y=2)
true
1Same fields, different class kinds: only the data class treats equal values as equal.
Remove data from Point and predict all four lines before running it.
equals, hashCode and toString. Two User objects with the same constructor values are equal even if a body property such as var loginCount differs. Put everything that defines identity in the constructor.data class User(val name: String) {
var loginCount = 0
}
fun main() {
val a = User("Ada")
val b = User("Ada")
a.loginCount = 5
println(a == b)
println(a)
}true
User(name=Ada)A data class with no constructor properties
data class Empty()
fun main() {
println(Empty())
}Main.kt:1:17: error: data class must have at least one primary constructor parameter.
data class Empty()
^^Everything a data class generates is built from its primary-constructor properties. With none, there is nothing to compare, hash or print, so the compiler refuses.
Give it at least one val/var parameter. If you really want a single value with nice printing, use data object instead (covered below).
data object Empty
fun main() {
println(Empty)
}