在抽象构造函数中访问overriden val时出现NullPointerException

时间:2011-01-15 19:40:19

标签: scala

考虑以下(简化)示例:

abstract class Bar[T] {
    val f: PartialFunction[T, T]
    val default: PartialFunction[T, T] = { case x => x }
    val chained = f orElse default
}

class Foo extends Bar[Int] {
    val f: PartialFunction[Int, Int] = { case 1 => 2 }
}

看着它崩溃:

scala> val foo = new Foo
java.lang.NullPointerException
        at Bar.<init>(<console>:8)
        at Foo.<init>(<console>:6)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at RequestResult$.<init>(<console>:9)
        at RequestResult$.<clinit>(<console>)
        at RequestResult$scala_repl_result(<console>)
        ....

但是,如果我们将chained放在具体类中:

abstract class Bar[T] {
    val f: PartialFunction[T, T]
    val default: PartialFunction[T, T] = { case x => x }
}

class Foo extends Bar[Int] {
    val f: PartialFunction[Int, Int] = { case 1 => 2 }
    val chained = f orElse default
}

按预期工作:

scala> val foo = new Foo
foo: Foo = Foo@16132c4

我不得不承认我完全不知道这里发生了什么。错误? (这是在Scala 2.8.1上。)

2 个答案:

答案 0 :(得分:5)

“为什么我的抽象或覆盖val为空?” https://github.com/paulp/scala-faq/wiki/Initialization-Order

答案 1 :(得分:0)

我的猜测:这是在编译时完成的优化。编译器会识别您覆盖f中的Bar。因此,Bar的“构造函数”首先执行来自Foo - sans f的内容! - 然后然后 Bar定义中的内容。因此,在构造f时未定义chained

我称之为bug。