何时使用伴侣对象工厂与新关键字

时间:2015-08-28 20:48:10

标签: scala conventions companion-object

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

该标准库。现在,在我自己的代码中,哪种方法更好用:伴侣工厂或用new创建对象?

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

使用一个优于另一个有什么好处?

2 个答案:

答案 0 :(得分:5)

在大多数情况下,我使用伴随对象的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 - 方法,但我不知道是否存在官方约定。

答案 1 :(得分:3)

我不知道有一种方法的一般建议,通常只是方便不必键入new

但是,有时候工厂方法选项会更好。例如,如果您的类具有必须为大写的String字段,则可以使标准构造函数为private,通过factory方法强制实例化,以确保该字段始终为大写:

class A private[A] (s: String)

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

注意:如果您的课程是一个案例类,那么还有其他一些调整可以让它完全发挥作用 - 请参阅here