Refactoring class hierarchy into ADT

My point is that if you use abstract vals or defs then you do not need constructors.

As such everything can be a trait or a final class / object; which can help you with your linearization issues.
Something like:

// instead of
abstract class FooImpl(bar: Int) {
  final def baz(x: Int): Int = bar * x
} 
final case class Foo(bar: Int) extends FooImpl(bar)

// you can
trait FooImpl {
  def bar: Int

  final def baz(x: Int): Int = bar * x
} 
final case class Foo(override final val bar: Int) extends FooImpl

Also, as @sangamon said, whereas your use case is legitimate. Things like ADTs with a lot of methods and depending on linearization order seems too OOP to me and very complex.
As I have mentioned before, for me everything is either abstract or final, I rarely find myself overriding something concrete and I have never needed to call my parent implementation, I personally would find that a nightmare to understand and change.
But, whatever, do not let my mental limitations to guide you :slight_smile:

About the private a self types, I guess you can see it here the reason for both is not exposing those to external users and avoiding mistakes like extending FooImpl from Bar.