I have the following case class implementing a trait with a generic method. The goal is to have each class S which extends the trait implement the method in a way that the method consumes a parameter of type S and returns a value of type S.
case class Foo(x: Int) extends Bar {
def baz[Foo](v: Foo): Foo = {
Foo(v.x + x)
}
}
trait Bar {
def baz[S <: Bar](v: S): S
}
However, when compiling this, I get the following error that x cannot be found.
error: value x is not a member of type parameter Foo
Foo(v.x + x)
^
one error found
Even stranger to me is that when I change the method to return Foo(3) (thus removing access to x), I get the following error:
error: type mismatch;
found : <empty>.Foo
required: Foo(in method baz)
Foo(3)
^
one error found
I'm not sure what the types <empty>.Foo and Foo(in method baz) are and why both of these aren't just Foo. There's obviously some things about Scala's type system I'm misunderstanding, so help clearing that up would be appreciated.
Edit
I expect to have multiple classes implementing Bar. I want to be able to call baz on vals of type Bar.
Consider in the example below that a and b are obtained from elsewhere and I know based on the logic of my program that they are both instances of the same class (not necessarily Foo). Is there any way to make a legal call to baz in this case? I know I could cast both to Foo, but this happens in a scenario where I don't know what the specific class is. That is, I know both a and b are of type T <: Bar for the same T, but I don't know what T is.
object Foo {
def main(args: Array[String]): Unit = {
val a: Bar[_] = Foo(3)
val b: Bar[_] = Foo(2)
a.baz(b) // This call is invalid
}
}