Я думаю, что есть две важные темы:
Неизменность
Я бы принял неизменность и не предоставлял какой-либо метод мутации в классах домена. Вы можете использовать метод copy
для создания нового экземпляра с различными неизменяемыми свойствами.
Идентичность
Класс данных использует все свойства, объявленные в конструкторе в методе equals. Это означает, что это класс значений, то есть он не имеет идентичности. Это значение, подобное Point (x, y). Два экземпляра Point (1,2) и Point (1,2) неразличимы. Они одинаковы, если все их свойства одинаковы.
Заключение
Используйте обычный class
для доменной сущности, такой как Пользователь . Используйте свойства, которые определяют личность вашей сущности, для реализации equals
, hashcode
, et c. Используйте data class
для значения домена, такого как Address . Для класса данных вполне нормально иметь функции, если они не содержат мутаций.
В вашем случае я бы реализовал нечто подобное:
data class Address(val streetName: String)
class Person(
val id: Int,
val name: String,
val age: Int,
val address: Address
) {
fun isAdult() = age >= 18
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Person
if (id != other.id) return false
return true
}
override fun hashCode(): Int {
return id
}
fun copy(
id: Int = this.id,
name: String = this.name,
age: Int = this.age,
address: Address = this.address) = Person(id, name, age, address)
override fun toString(): String {
return "Person(id=$id, name='$name', age=$age, address=$address)"
}
}
fun main() {
val personA = Person(123312, "Person A", 17, Address("Street 1"))
println(personA.isAdult())
println(personA.age)
val olderPersonA = personA.copy(age = 18)
println(olderPersonA.isAdult())
println(olderPersonA.age)
}
РЕДАКТИРОВАТЬ: Как вы сказали, есть возможность использовать класс данных и переопределять только equals и hashcode, но я не уверен, что это семантически правильно. Комментарии по этому поводу приветствуются.
data class Person(
val id: Int,
val name: String,
val age: Int,
val address: Address
) {
fun isAdult() = age >= 18
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Person
if (id != other.id) return false
return true
}
override fun hashCode(): Int {
return id
}
}