Scala: реализация метода с возвращаемым типом конкретного экземпляра

Мне нужен способ принудительного применения метода в абстрактном классе, чтобы иметь возвращаемый типбетон класс объекта он вызывается. Наиболее распространенным примером являетсяcopy() метод, и в настоящее время я использую подход, основанный на абстрактных типах:

abstract class A(id: Int) {
  type Self <: A
  def copy(newId: Int): Self
}

class B(id: Int, x: String) extends A(id) {
  type Self = B
  def copy(newId: Int) = new B(newId, x)
}

class C(id: Int, y: String, z: String) extends A(id) {
  type Self = C
  def copy(newId: Int) = new C(newId, y, z)
}

Я уже видел много подходов, в том числе вэтот великий ответ, Тем не менее, ни один из них на самом делесил реализация для возврата своего собственного типа. Например, следующие классы будут действительны:

class D(id: Int, w: String) extends A(id) {
  type Self = A
  def copy(newId: Int) = new D(newId, w) // returns an A
}

class E(id: Int, v: String) extends A(id) {
  type Self = B
  def copy(newId: Int) = new B(newId, "")
}

Тот факт, что я могу это сделать, приводит к тому, что, если я делаю копии объектов, единственная информация о которых у меня есть, это то, что они относятся к данному подклассуA«S:

// type error: Seq[A] is not a Seq[CA]!
def createCopies[CA <: A](seq: Seq[CA]): Seq[CA] = seq.map(_.copy(genNewId()))

Есть ли лучший, безопасный для типов способ, которым я могу сделать это?

РЕДАКТИРОВАТЬ: Если это возможно, я хотел бы сохранить возможность создания сколь угодно глубоких иерархий абстрактных классов. То есть в предыдущем примере я ожидаю, что смогу создатьАбстрактные классA2 это расширяетA, а затем приступить к созданиюA2Конкретные подклассы. Однако, если это упрощает проблему (как в случае с абстрактными типами), мне не нужно дополнительно расширять уже конкретные классы.

Ответы на вопрос(4)

Ваш ответ на вопрос