何时使用伴随对象工厂与 new 关键字

When to use companion object factory versus the new keyword

Scala 标准库中的许多 类 使用其伴随对象的 apply() 作为工厂。这在像 List(List(1)) 这样的链接调用时通常很方便。另一方面,仍然可以直接使用 new (new HashMap[Int, Int]()).

创建对象

那是标准库。现在,在我自己的代码中,哪种方法更适合使用:配套工厂还是使用 new?

创建对象

关于何时创建伴生对象工厂以及何时使用 new 关键字是否有约定?

使用一个比另一个有什么优势?

我不知道是否有一种方法优于另一种方法的一般建议,通常只是为了方便而不必键入 new

不过,在某些情况下,工厂方法选项可能会更好。例如,如果您的 class 有一个必须为大写的 String 字段,您可以将标准构造函数设为私有,通过确保该字段始终为大写的工厂方法强制实例化:

class A private[A] (s: String)

object A {
    def apply(s: String): A = new A(s.toUpperCase)
}

注意:如果您的 class 是 class 的情况,还有其他一些调整可以使其完全正常工作 - 请参阅

在大多数情况下,我使用伴随对象的 apply 方法,因为代码看起来不那么混乱。但是,使用静态工厂至少有一个好处。考虑一下没有想象力的类型 MyInt,它只是包装了一个 Int

class MyInt(val i: Int) 

我可以获得 MyInt 调用构造函数的实例,每次调用构造函数时都会实例化一个新对象。如果我的程序严重依赖 MyInt,这会导致创建大量实例。假设我使用的大多数 MyInt-101,因为 MyInt 是不可变的,我可以重复使用相同的实例:

class MyInt(val i: Int) 

object MyInt {
  val one = new MyInt(1)
  val zero = new MyInt(0)
  val minusOne = new MyInt(-1)

  def apply(i: Int) = i match {
    case -1 => minusOne
    case 0 => zero
    case 1 => one
    case _ => new MyInt(i)
  }
}

因此至少对于不可变值而言,使用静态工厂比调用构造函数具有技术优势。言外之意,如果你想在代码中表达一个新实例被创建,那么使用new关键字。就个人而言,我在创建对象时使用 new-关键字,在创建值时使用 apply-方法,尽管我不知道是否有官方约定。