Scala 标准库中的许多类都使用apply()
它们的伴生对象作为工厂。这在链接调用时通常很方便,例如List(List(1))
. 另一方面,仍然可以使用new
( new HashMap[Int, Int]()
) 直接创建对象。
那是标准库。现在,在我自己的代码中,哪种方法更好用:伴生工厂还是使用 ? 创建对象new
?
new
关于何时创建伴随对象工厂以及何时使用关键字是否有任何约定?
使用一个比另一个有什么优势?
Scala 标准库中的许多类都使用apply()
它们的伴生对象作为工厂。这在链接调用时通常很方便,例如List(List(1))
. 另一方面,仍然可以使用new
( new HashMap[Int, Int]()
) 直接创建对象。
那是标准库。现在,在我自己的代码中,哪种方法更好用:伴生工厂还是使用 ? 创建对象new
?
new
关于何时创建伴随对象工厂以及何时使用关键字是否有任何约定?
使用一个比另一个有什么优势?
在大多数情况下,我使用伴生对象的apply
方法,因为代码看起来不那么混乱。但是,使用静态工厂至少有一个好处。MyInt
考虑一下只包装了一个没有想象力的类型Int
:
class MyInt(val i: Int)
我可以获得调用构造函数的实例,MyInt
每次调用构造函数时都会实例化一个新对象。如果我的程序严重依赖MyInt
这会导致创建大量实例。假设MyInt
我使用的大部分是-1
、0
和1
,因为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,虽然我不知道是否有官方约定。
我不知道是否有一种方法优于另一种方法的一般建议,通常只是为了方便而不必键入new
.
但是,在某些情况下,工厂方法选项可能会更好。例如,如果您的类有一个必须为大写的 String 字段,您可以将标准构造函数设为私有,通过确保该字段始终为大写的工厂方法强制实例化:
class A private[A] (s: String)
object A {
def apply(s: String): A = new A(s.toUpperCase)
}
注意:如果您的课程是一个案例课程,还有一些其他的调整可以让它充分发挥作用 - 请参阅此处。