【发布时间】:2011-03-28 10:35:21
【问题描述】:
我想只使用不可变对象来构建我的域模型。但我也想将特征与 val 字段一起使用,并将一些功能移至特征。请看下面的例子:
trait Versionable {
val version = 0
def incrementVersion = copy(version=version+1)
}
不幸的是,这样的代码不起作用 - trait 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 trait 中。
我知道案例类中复制方法的功能以及使用默认参数在类中编写自己的复制方法的能力 - 但我认为这个功能不能解决我的问题,因为不可能使用这种复制方法在特质。现有功能的另一个缺点是使用复制方法的父类返回父类,而不是实际复制的对象的类。
我的问题:
1) 你知道如何优雅地处理上面的例子吗?我对 Scala 很陌生,所以也许已经有了很好的解决方案。在我看来,优雅的解决方案应该具有以下特点:
不应使用反射
不应使用序列化
应该很快
应该在编译时可验证
2) 对于我上面的例子,你对编写编译器插件来生成复制方法的代码有什么看法?是否可以使用编译器插件来做到这一点?您有任何示例或提示吗?
【问题讨论】:
-
您是否知道编译器赋予案例类以
copy方法,例如您所描述的?案例类不能(从技术上讲,不应该)从其他案例类派生。特别是,派生的案例类将继承超(案例)类的copy方法。 -
是的,我知道这一点,并且不会使用案例类来解决所描述的问题。我正在尝试寻找解决方案来编写具有特征的不可变类,这些特征不仅是 Java 中的接口,而且还增加了实现。此类特征中的“Mutator”方法应返回具有修改的“变异”字段的对象副本,但如何以优雅的方式做到这一点?
-
也许这个问题可以为您提供一些有用的方法来处理这个问题:stackoverflow.com/questions/3007464/…
-
我添加了一个相关问题:stackoverflow.com/questions/3471708/… 这也与我下面的(非工作)解决方案有关。
标签: scala immutability scala-2.8 traits