我想仅使用不可变对象构建我的域模型。但我也想将特征与 val 字段一起使用,并将一些功能移至特征。请看下面的例子:
trait Versionable {
val version = 0
def incrementVersion = copy(version=version+1)
}
不幸的是,这样的代码不起作用 - 对于特征版本化来说,复制方法是未知的。
我认为为每个特征和类生成复制方法会很好。此类方法应创建对象的浅表副本,并使用与原始对象相同的类型返回它,并根据传递给方法的参数修改给定字段。
所以在下面的例子中:
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")
and
customer.incrementVersion
还应该返回一个对象实例Customer(version = 1, name = "Scot")
据我所知,Scala 目前缺乏此类功能,不允许使用不可变的类和特征,而不用特征字段污染类构造函数。在我的示例中,我不想向 Customer 类引入名为 version 的参数,因为我希望将版本处理的功能封装在 Versionable 特征中。
我知道案例类中复制方法的功能以及使用默认参数在类中编写自己的复制方法的能力 - 但我认为此功能不能解决我的问题,因为不可能在特征中使用此类复制方法。现有功能的另一个缺点是使用复制方法的父类返回父类而不是实际复制的对象的类。
我的问题:
1)你知道如何以优雅的方式处理上面的例子吗?我对 Scala 很陌生,所以也许已经有很好的解决方案了。在我看来,优雅的解决方案应该具有以下特征:
不应该使用反射
不应该使用序列化
应该很快
应该在编译时可验证
2)您对编写编译器插件来为上面的示例生成复制方法的代码有何看法?是否可以使用编译器插件来做到这一点?您有任何示例或提示如何做到这一点吗?