Understanding data classes in kotlin

This is my class

class Foo<B>(private val b: B) {
 override fun equals...
 override fun hashCode...
}

If I do assertEquals(foo1, foo2) where foo1 and foo2 are of type Foo and if foo1 and foo2 are not equal, I get the error message like

Actual: Foo@f54e1c3c
Expected: Foo@ee2bcc2d

But if I change Foo to a data class (i.e just add the keyword data before class Foo) and execute the assert statement, then I get a detailed error message with the full values of foo1 and foo2 instead of the hashcode that was given in the former case. What magic does a data class bring in here?

data classes override toString(). You can do the same yourself with a regular class.

Data classes override the following methods:

  • toString
  • hashCode/equals
  • compnentN
  • copy

All of those function use the properties that are defined as part of the primary constructor and ignore all other properties

data class Foo(val p1: Int, val p2: Int){
    var p3: Int = 5
}

In this example only p1 and p2 are part of the implementation for the methods above. This means that you can change p3 and equals would still return true. Also this class would only have 2 `componentN´ functions (p1 and p2).

Also you can still override those methods with your own implementation. In that case the data class implementation for a method will be skipped.

data class Foo(val p1: Int){
    override fun toString() = "Changed toString of Foo: p1 = $p1"
}

In this case only hashCode, equals, copy and component1 will be created by the compiler.

You can find more info here: https://kotlinlang.org/docs/reference/data-classes.html