如何避免子类的伴随对象中的代码重复

How to avoid code duplication in companion objects of subclasses

我的 Scala 代码中有以下模式:

class A(x: Int)
object A {
  def apply(x: Int, y: Int) = new A(x + y)
}

class B(x: Int) extends A(x)
object B {
  def apply(x: Int, y: Int) = new B(x + y)
}

应用方法完全相同,除了它们构造的对象的Class。我想避免这种代码重复,特别是因为在我的真实代码中我有几个应用方法而且它们更长。

我怎样才能做到这一点?如何删除此代码重复?

我想过这样的事情:

class A(x: Int)
class B(x: Int) extends A(x)

trait C[T <: A] {
  def apply(x: Int, y: Int) = new T(x + y)
}

object A extends C[A]
object B extends C[B]

它不起作用,因为 T 不是 class,因此我不能 "new T(x + y)"。

我会提出这个解决方案:

class A(x: Int)
class B(x: Int) extends A(x)

trait C[+T <: A] {
  def apply(x: Int, y: Int) = create(x + y)
  protected def create(x: Int): T
}

object A extends C[A] {
  override protected def create(x: Int) = new A(x)
}
object B extends C[B] {
  override protected def create(x: Int) = new B(x)
}

看看GenericCompanion class。它是 Scala 集合库的一部分,可能会启发您: http://www.scala-lang.org/api/current/index.html#scala.collection.generic.GenericCompanion

在特定情况下,您可以执行类似

的操作
class A(x: Int) {
  def this(x: Int, y: Int) = this(x + y)
}
class B(x: Int) extends A(x)
class Adder[T](f: Int => T) {
  def apply(x: Int, y: Int) = f(x + y)
}

class A(x: Int)
object A extends Adder(new A(_))

class B(x: Int) extends A(x)
object B extends Adder(new B(_))