Use data types for meaningful equality
A data class generates equality, hashing, copying, destructuring, and a readable string representation from primary-constructor properties. Properties declared only in the body are excluded from those generated value operations.
data class Lesson(val id: String, val title: String)
data object Loading
fun main() {
val original = Lesson("k1", "Kotlin")
val renamed = original.copy(title = "Kotlin basics")
check(original.id == renamed.id)
check(original != renamed)
println(Loading)
}
copy is shallow: nested mutable objects remain shared. Avoid mutable properties involved in equality when instances are keys in a map or members of a hash set; changing them can make lookups inconsistent with the original hash placement.
A data object is useful for a named singleton state with generated value-style behavior. It is not a container for different instances with separate parameters.
Exercise
Add a mutable list property to a data class, copy an instance, and demonstrate the shared list. Then redesign it so updates return new list values.
Check: explain why copy() alone is not a deep immutability guarantee.