我正在开发一个基于Dozer构建的自动映射框架。我不会详细说明,因为它与问题无关,但一般来说它应该允许从A类到B类的简单转换。我想从类的伴随对象中注册投影。
以下是我希望如何工作的(简化)示例,以及确保投影正确注册的Specs测试。
不幸的是,这不起作用。从我可以收集到的,这是因为没有任何东西初始化A伴侣对象。事实上,如果我在A对象上调用任何方法(如注释掉的hashCode调用,则正在正确注册投影。
我的问题是 - 一旦JVM启动,我怎样才能自动初始化A对象?如果有必要的话,我不介意延长Trait或其他东西。
感谢。
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
}
}
答案 0 :(得分:12)
简短的回答:你做不到。 Scala对象是惰性的,直到第一次引用才初始化。您可以引用该对象,但是您需要一种方法来确保执行代码的执行,从而将问题还原到原始问题。
答案 1 :(得分:4)
最终做到了这一点:
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 :(得分:3)
您可以通过使用apply()方法或对象中定义的其他种类工厂方法来强制A
的实例化以涉及伴随对象,而不是直接使用new A()
构造函数。 / p>
这 not 导致JVM启动时对象被初始化,我认为通常不能在另一个答案中注明。
答案 3 :(得分:1)
正如Dave Griffith和Don Roby已经指出的那样,一般来说,JVM创业公司无法做到这一点。但是,这个初始化可能要等到第一次使用你的框架? 如果是这样,如果你不介意使用脆弱的反射技巧,在你的 - &gt;您可以获得对伴随对象的引用并使其初始化的方法。
答案 4 :(得分:0)
我们可以使用这种方式来确保先初始化伴生对象,然后再实例化类。
object B {
val i = 0
def apply(): B = new B()
}
class B {
// some method that uses i from Object B
def show = println(B.i)
}
// b first references Object B which calls apply()
// then class B is instantiated
val b = B()