避免在基本特征中初始化被覆盖的`val`?

时间:2015-06-30 10:45:33

标签: scala

在以下代码中:

trait Base {
  val foo: String = {
    println("Hi, I'm initializing foo in trait Base")
    "foo"
  }

}

class Overrider extends Base {
  override val foo = "bar!"
}

object Runner extends App {
  println(new Overrider().foo)
  println((new {override val foo = "baz"} with Base).foo)
}
无论是否通过扩展特征或使用早期初始化来覆盖 val ,都会调用

Base特征的foo值初始化:

Hi, I'm initializing foo in trait Base
bar!
Hi, I'm initializing foo in trait Base
baz

有没有办法使用val并避免发生这种情况,还是应该坚持使用lazy val

2 个答案:

答案 0 :(得分:3)

如您所述使用lazy valdef。 AFAIK没有其他方法可以避免在基类中初始化val。这是因为类成员定义之外的所有内容都进入构造函数。因此,val s将在施工时初始化。

另一种方法是定义一个扩展的接口:

trait Base {
  def foo: String
}

class Foo extends Base {
  override val foo = "foo"
}

class Bar extends Base {
  override val foo = "bar"
}

答案 1 :(得分:0)

当其他用户回答您的问题时,如果您不希望评估foo特征方法,则必须将def定义为Base

您在问题的评论中告诉我您正在尝试实施接线模块,如本link中所述。然后,你基本上试图实现薄蛋糕模式

在这种情况下,将foo声明为val在逻辑上不正确。 foo表示无法急切解决的依赖关系。如果使用val,则两个组件将紧密耦合。您必须将foo定义为def,以便让您的主应用程序(或测试)将foo连接到正确的类型,即具体类或模拟。

如果您想要更多解释,请告诉我。