I'd like to get a reference to the concrete type of a self-type annotation in Scala within the self-typed trait. I have something like this:
trait Foo
class FooImpl1 extends Foo
class FooImpl2 extends Foo
trait SpecialFoo {
this:Foo =>
def |+|(that:this.type):this.type // the type signature is incorrect here
}
where if I do new FooImpl1 with SpecialFoo
, I'd like the |+|
method to require and return a FooImpl1
(or a subtype of FooImpl1
). However, with the above code it seems to want a SpecialFoo.this.type
, which is unsurprising, but not what I want.
this.type
is the singleton type of whatever instance ofSpecialFoo
you have. As defined,|+|
would only be able to be called with itself. For example:this.type
isFooImpl1
in some cases, but the compiler has no way of knowing that. You need some way to capture the more refined type ofFooImpl1
orFooImpl2
. The self-typethis: Foo =>
only cares that it's aFoo
. There are a couple possibilities, but neither will look as nice as you want.You can parameterize
SpecialFoo
:Unforunately, you need to write
FooImpl1
twice, but the self-type still prevents you from mixing two different implementations.The alternative is to use type members within
Foo
. You wouldn't have to specify the implementation type twice when creating aSpecialFoo
, but would when creating the implementations themselves to bind the correct types.You could also make
Foo
F-bounded, i.e.trait Foo[A <: Foo]
, and do something similar to the above example.