强制初始化Scala单例对象

时间:2011-06-06 08:46:53

标签: scala object

我正在开发一个基于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
  }
}

5 个答案:

答案 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;您可以获得对伴随对象的引用并使其初始化的方法。

您可以从Getting object instance by string name in scala开始。

答案 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()