Принудительная инициализация одноэлементного объекта Scala - PullRequest
12 голосов
/ 06 июня 2011

Я работаю над структурой автоматического картографирования, построенной поверх Dozer.Я не буду вдаваться в подробности, так как это не имеет отношения к вопросу, но в целом должно допускать легкое преобразование из класса А в класс В. Я хотел бы зарегистрировать проекции из сопутствующего объекта класса.Ниже приведен (упрощенный) пример того, как я хочу, чтобы это работало, и тест спецификации, который гарантирует, что проекция регистрируется правильно.

К сожалению, это не работает.Из того, что я могу собрать, это потому, что ничто не инициализирует объект-компаньон А.И действительно, если я вызываю какой-либо метод объекта 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
  }
}

Ответы [ 4 ]

12 голосов
/ 06 июня 2011

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

4 голосов
/ 09 июня 2011

В конечном итоге сделал это:

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 при загрузке приложения. Не идеально, но у меня работает.

3 голосов
/ 06 июня 2011

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

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

1 голос
/ 06 июня 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...