PHondogo
03/19/2024, 9:10 AMabstract class T1 {
var x = 5
}
data class T2(
val y: Int
) : T1()
@Test
fun test() {
val a = T2(y=10)
a.x = 100
val b = a.copy(y = 99)
println(b.x) // 5 // why x is not copied?
}
hfhbd
03/19/2024, 9:13 AMPHondogo
03/19/2024, 9:16 AMJoffrey
03/19/2024, 9:39 AMequals
, hashcode
, toString
, and copy
. They all only consider the parameters from the constructor. It's just how they are designed:
> The compiler automatically derives the following members from all properties declared in the primary constructorPHondogo
03/19/2024, 9:47 AMephemient
03/19/2024, 9:57 AMCLOVIS
03/19/2024, 10:17 AMThanks, but why it is allowed? It is confusing behavior.It's only confusing if the additional property are completely unrelated to the data in the primary constructor. But in this case, a
data class
is not the right abstraction.
Here's an example with additional properties that is not confusing at all and works as expected:
data class Foo(
val prefix: String,
val postfix: String,
) {
val full by lazy {
"$prefix${expensiveOperation()}$postfix"
}
}
In this case, copy
, equals
, hashCode
etc all work as expected.
Data class really do represent "data". Their identity is the contents of the primary constructor. You shouldn't have anything outside the primary constructor that you want to be part of the data.PHondogo
03/19/2024, 10:18 AM