[Примечание: я не рекомендую вам делать это.] Есть большая вероятность, что вы сможете достичь того, чего хотите. Приведение к this.type является ложью, но JVM не знает этого и не может выдать исключение, потому что синглтон-тип является концепцией scala.
Теперь, если вы на самом деле где-то используете свойство singleton этого thistype, это быстро доставит вам неприятности. Но если все, что вы хотите сделать, это получить ковариантные типы возвращаемых данных без необходимости набирать их, только с небольшой обратной стороной огромного уродливого приведения повсеместно:
trait Expression
{
def left : Expression
def right : Expression
def new_with_changes(l : Expression, r : Expression) : this.type
}
case class Derived1(left : Expression, right : Expression) extends Expression {
def new_with_changes(l : Expression, r : Expression) =
Derived1(left, right).asInstanceOf[this.type]
def foo() = "Derived1"
}
case class Derived2(left : Expression, right : Expression) extends Expression {
def new_with_changes(l : Expression, r : Expression) =
Derived2(left, right).asInstanceOf[this.type]
def bar() = "Derived2"
}
И в действии:
scala> Derived1(Derived1(null,null), null)
res0: Derived1 = Derived1(Derived1(null,null),null)
scala> res0.new_with_changes(res0, null).bar
<console>:6: error: value bar is not a member of Derived1
res0.new_with_changes(res0, null).bar
^
scala> res0.new_with_changes(res0, null).foo
res2: java.lang.String = Derived1
scala> Derived2(Derived2(null, null), null)
res3: Derived2 = Derived2(Derived2(null,null),null)
scala> res3.new_with_changes(null, res3).foo
<console>:6: error: value foo is not a member of Derived2
res3.new_with_changes(null, res3).foo
^
scala> res3.new_with_changes(null, res3).bar
res6: java.lang.String = Derived2