Как объявить конструктор для типа класса "объект" в Scala? I.e., однократная операция для одноэлементного

Я знаю, что объекты обрабатываются в значительной степени подобно синглонам в scala. Тем не менее, я не смог найти элегантный способ указать поведение по умолчанию при первоначальном экземпляре. Я могу выполнить это, просто поместив код в тело декларации объекта, но это кажется чрезмерно взломанным. Использование приложения действительно не работает, потому что его можно вызвать несколько раз и на самом деле не имеет смысла для этого варианта использования.

Любые идеи о том, как это сделать?

Ответ 1

Классы и объекты запускают код в своем теле после создания экземпляра, по дизайну. Почему это "хаки"? Это как язык должен работать. Если вам нравятся дополнительные фигурные скобки, вы всегда можете их использовать (и они будут сохранять локальные переменные и сохраняться в мире).

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

Ответ 2

Rex имеет все права, я просто хотел указать на шаблон, который я использую много, что избавляет вас от необходимости использовать vars, избегая при этом загрязнения пространства имен промежуточными значениями.

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

Ответ 3

Если вам становится лучше, вы можете создать некоторый класс с защищенным конструктором, а 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() {
    ...
  }
}

Ответ 4

Тело объявлений объектов и классов является конструктором по умолчанию, и любой код, размещенный в нем, будет выполняться при первой ссылке, так что это именно то, как это сделать.