Extended Data Class dangers

I was trying to build data classes for Android Room. Coming from Java, I had my data classes always carry the fields “id” and “last_updated”, so I extended those classes.

In Kotlin data classes can not be extended, but you can extend a data class with an abstract class.

abstract class TestBase {
    var id: Long = 0 // given by database
    val last_update = System.currentTimeMillis() // given by database
}

data class PersonData(var personName: String = ""):TestBase() {
}

There is no compiler warning.

However, if I want to use the benefits of a data class I am flabbergasted:

    val person1 = PersonData("Smith")
    person1.id = 1
    val person2 = PersonData("Smith")
    person1.id = 2

    val isEqual = person1.equals(person2)
    val isEqual2 = person1 == person2
    println("Person1 equals Person2: $isEqual, $isEqual2")

The two persons are wrongly regarded as the same.
I noticed, because I needed the ID in toString(), which was missing.

Data Classes should not be allowed to be extended if these kind of results are the outcome.

At first in Kotlin 1.0 inheritance in data classes was forbidden, but it was too restrictive in practice. In that case it’s a developer’s responsibility to make sure that a hashCode()/equals() contract is correct.

2 Likes