Objetos e características imutáveis de Scala com campos val
Gostaria de construir meu modelo de domínio usando apenas objetos imutáveis. Mas também quero usar características com campos val e mover algumas funcionalidades para características. Por favor, veja o seguinte exemplo:
trait Versionable {
val version = 0
def incrementVersion = copy(version=version+1)
}
Infelizmente, esse código não funciona - o método de cópia é desconhecido para a característica Versionável.
Eu acho que seria bom ter um método de cópia gerado para cada característica e classe. Esse método deve criar uma cópia superficial do objeto e retorná-lo usando o mesmo tipo que para o objeto original com o campo modificado de acordo com os argumentos passados para o método.
Então, no exemplo a seguir:
class Customer(val name: String) extends Versionable {
def changeName(newName: String) = copy(name = newName)
}
val customer = new Customer("Scot")
customer.changeName("McDonnald")
deve retornar uma instância de objetoCustomer(version = 0, name = "McDonnald")
e
customer.incrementVersion
também deve retornar uma instância de objetoCustomer(version = 1, name = "Scot")
Até onde eu sei, a atual falta dessa funcionalidade no Scala não permite usar classes e características imutáveis sem poluir o construtor de classes com os campos de características. No meu exemplo, não quero introduzir o parâmetro nomeado version na classe Customer, porque a funcionalidade do tratamento de versões eu quero ter encapsulado na característica Versionable.
Conheço a funcionalidade do método de cópia nas classes de caso e a capacidade de escrever o próprio método de cópia na classe usando parâmetros padrão - mas acho que essa funcionalidade não resolve o meu problema porque não é possível usar esse método de cópia nas características. Outra desvantagem da funcionalidade existente é que a classe pai usando o método copy retorna a classe pai e não a classe do objeto que é realmente copiado.
Minhas perguntas:
1) você tem idéia de como lidar com o exemplo acima de maneira elegante. Eu sou bastante novo no Scala, então talvez já exista uma boa solução. Na minha opinião, soluções elegantes devem ter os seguintes recursos:
não deve usar reflexão
não deve usar serialização
deve ser rápido
deve ser verificável em tempo de compilação
2) o que você acha de escrever um plug-in de compilador para gerar código para o método de cópia no meu exemplo acima? É possível fazer isso usando o plugin do compilador? Você tem exemplos ou dicas de como fazer isso?