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?

questionAnswers(5)

yourAnswerToTheQuestion