this.type
is a type the only instances of which are this
and Nothing
. When a method returns this.type
, the only allowed return value is this
. In class Test
applyMutation
doesn't return this
, but rather a completely new Test
, which isn't an instance of this.type
. This is why the code does not type-check.
I think what you are really trying to do is declare that applyMutation returns a value of the same class as this
. Doing this does indeed require F-Bounded polymorphism. Here is a rewritten version of your code:
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
}