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.typeis the singleton type of whatever instance ofSpecialFooyou have. As defined,|+|would only be able to be called with itself. For example:this.typeisFooImpl1in some cases, but the compiler has no way of knowing that. You need some way to capture the more refined type ofFooImpl1orFooImpl2. 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
FooImpl1twice, 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
FooF-bounded, i.e.trait Foo[A <: Foo], and do something similar to the above example.