如何在 Scala 中为“对象”类类型声明构造函数?即,单例的一次性操作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5200247/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I declare a constructor for an 'object' class type in Scala? I.e., a one time operation for the singleton
提问by Zack
I know that objects are treated pretty much like singletons in scala. However, I have been unable to find an elegant way to specify default behavior on initial instantiation. I can accomplish this by just putting code into the body of the object declaration but this seems overly hacky. Using an apply doesn't really work because it can be called multiple times and doesn't really make sense for this use case.
我知道对象在 Scala 中的处理方式与单身人士非常相似。但是,我一直无法找到一种优雅的方式来指定初始实例化时的默认行为。我可以通过将代码放入对象声明的主体来实现这一点,但这似乎过于hacky。使用 apply 并没有真正起作用,因为它可以被多次调用并且对于这个用例没有意义。
Any ideas on how to do this?
关于如何做到这一点的任何想法?
回答by Rex Kerr
Classes and objects both run the code in their body upon instantiation, by design. Why is this "hacky"? It's how the language is supposed to work. If you like extra braces, you can always use them (and they'll keep local variables from being preserved and world-viewable).
按照设计,类和对象都在实例化时在其主体中运行代码。为什么这是“黑客”?这就是语言应该如何工作。如果你喜欢额外的大括号,你可以随时使用它们(它们会防止局部变量被保留和世界可见)。
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
回答by Alex Cruise
Rex has it right, I just wanted to point out a pattern I use a lot, that saves you from having to use vars, while avoiding namespace pollution by intermediate values.
Rex 说得对,我只是想指出一个我经常使用的模式,它使您不必使用 var,同时避免中间值对命名空间的污染。
object Foo {
val somethingFooNeeds = {
val intermediate = expensiveCalculation
val something = transform(intermediate)
something
}
}
回答by tenshi
If it makes you feel better, you can create some class with protected constructor and objectwill create singleton of this class:
如果它让您感觉更好,您可以创建一些带有受保护构造函数的类,object并将创建此类的单例:
sealed class MyClass protected (val a: String, b: Int) {
def doStuff = a + b
}
object MyObject extends MyClass("Hello", b = 1)
Also notice, that sealedstops other classes and objects to extend MyClassand protectedwill not allow creation of other MyClassinstances.
另请注意,这会sealed阻止其他类和对象进行扩展,MyClass并且protected不允许创建其他MyClass实例。
But I personally don't see any problems with some code in the body of the object. You can also create some method like initand just call it:
但我个人认为对象主体中的某些代码没有任何问题。您还可以创建一些方法,例如init并调用它:
object MyObject {
init()
def init() {
...
}
}
回答by Martin Ring
The body of object and class declarations IS the default constructor and any code placed in there will be executed upon first reference, so that is exactly the way to do it.
对象和类声明的主体是默认构造函数,放置在其中的任何代码都将在第一次引用时执行,因此这正是执行此操作的方法。

