Инициализация силы объекта 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
}
}
Ответы
Ответ 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.