我知道对象的处理方式与scala中的单例非常相似。但是,我一直无法找到一种优雅的方法来指定初始实例化时的默认行为。我可以通过将代码放入对象声明的主体来实现这一点,但这看起来过于hacky。使用apply并不真正起作用,因为它可以被多次调用,并且对于这个用例并没有真正意义。
关于如何做到这一点的任何想法?
答案 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)
对象和类声明的主体是默认构造函数,放在那里的任何代码都将在第一次引用时执行,因此这正是执行它的方法。