首页 文章

为什么val和def在不同的时间实现抽象方法?

提问于
浏览
3

我正在使用scala并做了类似这样的事情:

trait Foo { val a: String }
trait Foo2 extends Foo { val a = "foo" }
trait Bar extends Foo { val b = a + "-bar" }
object Bar2 extends Bar with Foo2

我预计Bar2.b将是“foo-bar”,但它最终会成为“null-bar” . 如预期的那样,Bar2.a是“foo” .

如果我从val更改为def来定义'a',如下所示:

trait Foo { def a: String }
trait Foo2 extends Foo { val a = "foo" }
trait Bar extends Foo { val b = a + "-bar" }
object Bar2 extends Bar with Foo2

Bar2.b实际上是“foo-bar” .

在示例2中,在评估val'b'之前,来自Foo2的def'a'在Foo中实现抽象的def'a'被置于Bar2的定义中 . 在示例1中,在Bar / Bar2中定义val'b'之后,来自Foo2的val'a'覆盖来自Foo的val'a' .

为什么会这样?为什么val和def在不同的时间实现抽象方法?

2 回答

  • 3

    您总是希望在特征中使用 deflazy val (而不仅仅是 val )以避免您发现的尴尬行为 .

    至于为什么,从Scala Days 2012获得Scala 's implementation in the JVM, check out Josh Suereth'优秀演讲的低级细节 .

  • 4

    这是因为背后有Java . 初始化(非抽象)val被转换为具有私有字段的公共getter,并且它们按特定顺序初始化 . 抽象的vals只是吸气剂 . 检查Java文档 . 您还可以看到Scala的早期初始化器功能,以找到更好的解决方案:In Scala, what is an "early initializer"?

    还有混合的顺序 . 这应该给你正确的结果:

    object Bar2 extends Foo2 with Bar
    

相关问题