I want to define a method in a Scala trait where both a parameter to the method and the return type correspond to the same concrete class which extends the trait. I've tried something like the following:
trait A {
def foo(obj: this.type): this.type
}
final case class B(val bar: Int) extends A {
override def foo(obj: B): B = {
B(obj.bar + this.bar)
}
}
object Main {
def main(args: Array[String]) = {
val b1 = new B(0)
val b2 = new B(0)
val b3: B = b1.foo(b2)
}
}
However, trying to compile this code gives the following error:
Test.scala:5: error: class B needs to be abstract. Missing implementation for:
def foo(obj: B.this.type): B.this.type // inherited from trait A
case class B(val bar: Int) extends A {
^
Test.scala:6: error: method foo overrides nothing.
Note: the super classes of class B contain the following, non final members named foo:
def foo: ((obj: _1.type): _1.type) forSome { val _1: B }
override def foo(obj: B): B = {
^
2 errors
There's obviously something I'm misunderstanding about the Scala type system here. The signature of foo
in class B
is what I want it to be, but I don't know how to correctly define the method in A
(or if this is even possible). It seems like this question is asking something quite similar, but I don't immediately see how the answer applies in my situation.
this.type
, and it'sthis
. Your "override" says "I'll take a B and return some, maybe other, instance of B" which is not specific enough. – Oleg Pyzhcov