如何在Scala中为“对象”类类型声明构造函数?即,单身人士的一次性操作

时间:2011-03-04 23:05:48

标签: scala

我知道对象的处理方式与scala中的单例非常相似。但是,我一直无法找到一种优雅的方法来指定初始实例化时的默认行为。我可以通过将代码放入对象声明的主体来实现这一点,但这看起来过于hacky。使用apply并不真正起作用,因为它可以被多次调用,并且对于这个用例并没有真正意义。

关于如何做到这一点的任何想法?

4 个答案:

答案 0 :(得分:38)

类和对象在实例化时都按设计运行代码。为什么这个“hacky”?这就是语言的运作方式。如果你喜欢额外的大括号,你可以随时使用它们(并且它们将保持局部变量不被保存和世界可见)。

object Initialized {
  // Initalization block
  {
    val someStrings = List("A","Be","Sea")
    someStrings.filter(_.contains('e')).foreach(s => println("Contains e: " + s))
  }

  def doSomething { println("I was initialized before you saw this.") }
}

scala> Initialized.doSomething
Contains e: Be
Contains e: Sea
I was initialized before you saw this.

scala> Initialized.someStrings
<console>:9: error: value someStrings is not a member of object Initialized
       Initialized.someStrings

答案 1 :(得分:18)

Rex说得对,我只是想指出一个我经常使用的模式,这样可以避免使用变量,同时避免中间值对命名空间的污染。

object Foo {
  val somethingFooNeeds = {
    val intermediate = expensiveCalculation
    val something = transform(intermediate)
    something
  }
}

答案 2 :(得分:12)

如果它让你感觉更好,你可以用受保护的构造函数创建一个类,object将创建这个类的单例:

sealed class MyClass protected (val a: String, b: Int) {
  def doStuff = a + b
}

object MyObject extends MyClass("Hello", b = 1)

另请注意,sealed停止扩展MyClass的其他类和对象,而protected将不允许创建其他MyClass个实例。

但我个人认为对象体内的某些代码没有任何问题。您还可以创建一些方法,例如init,然后调用它:

object MyObject {
  init()

  def init() {
    ...
  }
}

答案 3 :(得分:4)

对象和类声明的主体是默认构造函数,放在那里的任何代码都将在第一次引用时执行,因此这正是执行它的方法。