You can also use self types to separate the implementation code into different files:
//T.scala
package foo
sealed trait T {
...
}
case class C1(..) extends T with C1Impl
case class C2(..) extends T with C2Impl
case class C3(..) extends T with C3Impl
case class C4(..) extends T with C4Impl
//C1Impl.scala
package foo
private[foo] trait C1Impl { this: C1 =>
// lots of implementation code
}