11

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

那是标准库。现在,在我自己的代码中,哪种方法更好用:伴生工厂还是使用 ? 创建对象new

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

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

4

2 回答 2

6

在大多数情况下,我使用伴生对象的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在创建对象时使用-keyword,apply在创建值时使用-method,虽然我不知道是否有官方约定。

于 2015-08-29T08:34:34.853 回答
3

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

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

class A private[A] (s: String)

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

注意:如果您的课程是一个案例课程,还有一些其他的调整可以让它充分发挥作用 - 请参阅此处

于 2015-08-28T23:50:36.637 回答