Подтвердить что ты не робот

Инициализация силы объекта Scala singleton

Я работаю над автоматической картой отображения, созданной поверх Dozer. Я не буду вдаваться в подробности, поскольку это не относится к вопросу, но в целом оно должно допускать легкое преобразование из класса A в класс B. Я хотел бы зарегистрировать проекции из объекта сопутствующего класса.

Ниже представлен (упрощенный) пример того, как я хочу, чтобы это сработало, и тест Specs, который гарантирует правильную регистрацию проекции.

К сожалению, это не работает. Из того, что я могу собрать, это потому, что ничего не инициализирует объект-компаньон. И действительно, если я вызываю какой-либо метод для объекта A (например, закомментированный вызов hashCode, проекция регистрируется правильно.

Мой вопрос: как я могу заставить объект A инициализироваться автоматически, как только запускается JVM? Я не возражаю против того, чтобы придать черту или что-то в этом роде.

Спасибо.

class A {
  var data: String = _
}

class B {
  var data: String = _
}

object A {
  projekt[A].to[B]

}

"dozer projektor" should {
  "transform a simple bean" in {
//    A.hashCode
      val a = new A
      a.data = "text"
      val b = a.-->[B]

      b.data must_== a.data
  }
}
4b9b3361

Ответ 1

В итоге это сделало:

trait ProjektionAware with DelayedInit
{
  private val initCode = new ListBuffer[() => Unit]

  override def delayedInit(body: => Unit)
  {
    initCode += (() => body)
  }


  def registerProjektions()
  {
    for (proc <- initCode) proc()
  }
}

object A extends ProjektionAware {
  projekt[A].to[B]

}

Теперь я могу использовать библиотеку сканирования классов для инициализации всех экземпляров ProjektionAware при загрузке приложения. Не идеально, но работает для меня.

Ответ 2

Короткий ответ: вы не можете. Scala объекты являются ленивыми и не инициализируются до первой ссылки. Вы можете ссылаться на объект, но тогда вам нужен способ обеспечения выполнения исполняемого кода, уменьшая проблему до исходной проблемы.

Ответ 3

Вы можете заставить экземпляр A задействовать объект-компаньон с помощью метода apply() или другого метода factory, определенного в объекте, вместо прямого использования конструктора new A().

Это не приводит к инициализации объекта при запуске JVM, который, как мне кажется, как указано в другом ответе, вообще не может быть выполнен.

Ответ 4

Как уже отмечал Дэйв Гриффит и Дон Роби, это не может быть сделано при запуске JVM в целом. Однако, возможно, эта инициализация может подождать до первого использования вашей инфраструктуры? Если да, и если вы не возражаете против хрупких трюков с отражением, в методе → вы можете получить ссылку на объект-компаньон и получить его инициализацию.

Вы можете начать с Получить экземпляр объекта по имени строки в scala.