Я хотел бы построить свою модель предметной области, используя только неизменяемые объекты. Но я также хочу использовать черты с полями 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) Что вы думаете о написании плагина компилятора для генерации кода для метода копирования для моего примера выше? Возможно ли это сделать с помощью компилятора? У вас есть примеры или советы, как это сделать?