我希望能够使用this.type来定义一个创建不可变案例类的新实例的方法.像这样的东西:
trait Expression
{
def left : Expression
def right : Expression
def new_with_changes(l : Expression, r : Expression) : this.type
}
case class Derived(left : Expression, right : Expression)
{
def new_with_changes(l : Expression, r : Expression) : this.type =
{
new Derived(left, right)
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,编译器抱怨
test.scala:13: error: type mismatch;
found : Derived
required: Derived.this.type
new Derived(left, right)
^
one error found
Run Code Online (Sandbox Code Playgroud)
为什么新案例类与this.type不匹配?
如果我将this.type更改为Base.new_with_changes中的Base并且Derived.new_with_changes中的Derived可以工作,但似乎它错过了this.type的精确性.
编辑:问题的真正意图是为什么在Scala中没有一个等效的方式来声明down的调用者执行downcast,就像this.type那样,但是对于一般类型.我认为这不容易,但它会很好.
我想仅使用不可变对象构建我的域模型.但我也想使用具有val字段的特征并将一些功能移到特征中.请看下面的例子:
trait Versionable {
val version = 0
def incrementVersion = copy(version=version+1)
}
Run Code Online (Sandbox Code Playgroud)
不幸的是这样的代码不起作用 - 对于特性Versionable,复制方法是未知的.
我认为为每个特征和类生成复制方法会很好.这样的方法应该创建对象的浅拷贝,并使用与原始对象相同的类型返回它,并根据传递给方法的参数修改给定的字段.
所以在下面的例子中:
class Customer(val name: String) extends Versionable {
def changeName(newName: String) = copy(name = newName)
}
val customer = new Customer("Scot")
Run Code Online (Sandbox Code Playgroud)
customer.changeName("McDonnald") 应该返回一个对象实例 Customer(version = 0, name = "McDonnald")
和
customer.incrementVersion 还应该返回一个对象实例 Customer(version = 1, name = "Scot")
据我所知,目前Scala中缺少此类功能不允许使用不可变类和特征而不会污染具有特征字段的类构造函数.在我的示例中,我不想将参数命名版本引入Customer类,因为版本处理的功能我想要封装在Versionable特性中.
我知道案例类中复制方法的功能以及使用默认参数在类中编写自己的复制方法的能力 - 但我认为这个功能并不能解决我的问题,因为在特征中不可能使用这种复制方法.现有功能的另一个缺点是使用复制方法的父类返回父类而不是实际复制的对象类.
我的问题:
1)您是否知道如何以优雅的方式处理上述示例.我对Scala很新,所以也许已经有了很好的解决方案.在我看来,优雅的解决方案应具有以下功能:
不应该使用反射
不应该使用序列化
应该快
应该在编译时可以验证
2)您如何考虑编写编译器插件来为我上面的示例生成复制方法的代码?是否可以使用编译器插件来做到这一点?您有任何示例或提示如何做到这一点?