Trait with a method returning the actual type that extends the trait

Often I have to write code like this:

  trait MyTrait[A <: MyParentTrait]:
    def myMethod: A = ... impl in trait ...

I have to have a type arg A with the only purpose that a call to myMethod returns the actual type extending MyTrait:

case class MyClassExt(...) extends MyParentTrait with MyTrait[MyClassExt]

Having the type arg A is complicated/hard to manage. Is there any way of having myMethod return MyClassExt (or whatever type extends MyTrait) without the type arg?

There’s some reading on this subject at Scala FAQ | Scala Documentation

1 Like

Among the things mentioned in that FAQ, I would recommend using a type member instead.

trait MyTrait:
    type This
    def myMethod: This = ... impl in trait ...

class MyClass extends MyTrait:
    type This = MyClass
2 Likes

Just to add, the usage shown by Martin above is explained in much more detail in Programming in Scala, 5th edition, Chapter 20.6 “Abstract Types”.

Reading the books pays off! :smiley:

2 Likes

Thanks all, I ended up using the type This solution. I have more than 100 case classes (and more will be added in the future) and for a start it seemed the smallest change. Also not sure what 100+ implicits will do for compilation times if I ended up doing the type classes solution.

Anyway a few hours later I changed several traits that was using the trait X[A] pattern. It all works well and the code is simpler now. Only thing I have to declare type This on every case class, I suppose there is no shortcut to declare it on the parent trait like trait MyParentTrait: type This = this.class.type

2 Likes