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

发布于 2024-10-20 21:57:25 字数 176 浏览 2 评论 0原文

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

关于如何做到这一点有什么想法吗?

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.

Any ideas on how to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

讽刺将军 2024-10-27 21:57:25

按照设计,类和对象都在实例化时在其主体中运行代码。为什么这是“黑客”?这就是语言应该如何工作的。如果您喜欢额外的大括号,则可以随时使用它们(它们将阻止局部变量被保留和全局可见)。

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

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
浴红衣 2024-10-27 21:57:25

Rex 说得对,我只是想指出我经常使用的一种模式,它可以让您不必使用变量,同时避免中间值造成名称空间污染。

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

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.

object Foo {
  val somethingFooNeeds = {
    val intermediate = expensiveCalculation
    val something = transform(intermediate)
    something
  }
}
蝶…霜飞 2024-10-27 21:57:25

如果这让您感觉更好,您可以创建一些带有受保护构造函数的类,并且 object 将创建此类的单例:

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

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

另请注意,sealed 会阻止其他类和对象扩展MyClassprotected 不允许创建其他 MyClass 实例。

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

object MyObject {
  init()

  def init() {
    ...
  }
}

If it makes you feel better, you can create some class with protected constructor and object will create singleton of this class:

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

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

Also notice, that sealed stops other classes and objects to extend MyClass and protected will not allow creation of other MyClass instances.

But I personally don't see any problems with some code in the body of the object. You can also create some method like init and just call it:

object MyObject {
  init()

  def init() {
    ...
  }
}
故事灯 2024-10-27 21:57:25

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文