Я хотел бы построить мою модель домена, используя только неизменяемые объекты. Но я также хочу использовать черты с полями val и переместить некоторые функции в свойства. Посмотрите следующий пример:
trait Versionable {
val version = 0
def incrementVersion = copy(version=version+1)
}
К сожалению, такой код не работает - метод копирования неизвестен для свойства Versionable.
Я думаю, что было бы неплохо создать метод копирования для каждого признака и класса. Такой метод должен создавать неглубокую копию объекта и возвращать его с использованием того же типа, что и для исходного объекта, с заданным полем, модифицированным по аргументам, переданным методу.
Итак, в следующем примере:
class Customer(val name: String) extends Versionable {
def changeName(newName: String) = copy(name = newName)
}
val customer = new Customer("Scot")
customer.changeName("McDonnald")
должен возвращать экземпляр объекта Customer(version = 0, name = "McDonnald")
и
customer.incrementVersion
должен также возвращать экземпляр объекта Customer(version = 1, name = "Scot")
Насколько я знаю, нынешняя нехватка таких функциональных возможностей в Scala не позволяет использовать неизменяемые классы и черты без использования класс-конструктора классов с полями признаков. В моем примере я не хочу вводить параметр с именем version в класс Customer, потому что функциональность обработки версий, которую я хочу инкапсулировать в черту Versionable.
Я знаю функциональность метода копирования в классах классов и возможность писать собственный метод копирования в классе с использованием параметров по умолчанию - но я думаю, что эта функциональность не решает мою проблему, потому что невозможно использовать такой метод копирования в чертах. Другим недостатком существующей функциональности является то, что родительский класс с использованием метода copy возвращает родительский класс, а не класс объекта, который фактически скопирован.
Мои вопросы:
1) у вас есть идея, как правильно выработать пример выше. Я новичок в Scala, поэтому, возможно, уже есть хорошее решение. На мой взгляд, элегантные решения должны иметь следующие функции:
-
не следует использовать отражение
-
не следует использовать сериализацию
-
должен быть быстрым
-
следует проверять во время компиляции
2) что вы думаете о написании плагина компилятора для генерации кода для метода копирования для моего примера выше? Можно ли это сделать с помощью плагина компилятора? У вас есть примеры или советы, как это сделать?