我有一个名为Mutatable的特性,它会吐出一个实现类的修改副本。我还有一个特性,我想在它上面堆叠,称为CostedMutatable,它跟踪这样做的成本。 applyMutation方法返回一个Option,后面我想在特定的变异不适用的情况下返回None。
一个简单的版本只适用于Ints(并通过添加新数字“变异”它们)如下所示:
trait Mutatable[M] {
def applyMutation(mut : M) : Option[this.type]
}
trait CostedMutatable[M] extends Mutatable[M]{
var cost : Int = _
def getCostFor(mut : M): Int
abstract override def applyMutation(mut : M) : Option[this.type] = {
cost += getCostFor(mut)
applyMutation(mut)
}
}
object Example extends App {
case class Mutation(x: Int)
class Test(s: Int) extends Mutatable[Mutation] {
val start = s
override def applyMutation(mut: Mutation): Option[Test]
= Some(new Test(s+mut.x))
}
class CostTest(s: Int) extends Test(s) with CostedMutatable[Mutation] {
override def getCostFor(mut: Mutation): Int = 2
}
val testCost = new CostTest(5).cost
}
问题是,这不会编译。我在编译时遇到以下错误:
Error:(23, 18) overriding method applyMutation in trait Mutatable of type (mut: Example.Mutation)Option[Test.this.type];
method applyMutation has incompatible type
override def applyMutation(mut: Mutation): Option[Test] = Some(new Test(s+mut.x))
^
除了编译器错误之外,还会想到另一个问题:我是否正确地接近这个问题?我应该使用F-bounded类型吗? (我需要每个新的实现类从applyMutation返回具体实现类的新副本。)
提前致谢。
答案 0 :(得分:2)
this.type
是一种类型,其唯一的实例是this
和Nothing
。当方法返回this.type
时,唯一允许的返回值为this
。在课程Test
中,applyMutation
不会返回this
,而是返回一个全新的Test
,它不是this.type
的实例。这就是代码不进行类型检查的原因。
我认为你真正要做的是声明applyMutation返回与this
相同的类的值。这样做确实需要F-Bounded多态性。以下是您的代码的重写版本:
trait CostedMutatable[+A <: CostedMutatable[A, M], M] extends Mutatable[A, M] {
var cost : Int = _
def getCostFor(mut : M): Int
abstract override def applyMutation(mut: M): Option[A] = {
cost += getCostFor(mut)
super.applyMutation(mut)
}
}
object Example extends App {
case class Mutation(x: Int)
class Test(s: Int) extends Mutatable[Test, Mutation] {
val start = s
override def applyMutation(mut: Mutation): Option[Test]
= Some(new Test(s+mut.x))
}
class CostTest(s: Int) extends Test(s) with CostedMutatable[CostTest, Mutation] {
override def getCostFor(mut: Mutation): Int = 2
}
val testCost = new CostTest(5).cost
}