NullPointerException при доступе к переопределенному значению val в абстрактном конструкторе - PullRequest
6 голосов
/ 15 января 2011

Рассмотрим следующий (упрощенный) пример:

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 ]

5 голосов
/ 15 января 2011

"Почему мой абстрактный или переопределенный val null?"https://github.com/paulp/scala-faq/wiki/Initialization-Order

0 голосов
/ 15 января 2011

Мое предположение: это оптимизация, выполненная во время компиляции. Компилятор распознает, что вы переопределяете f в Bar. Поэтому «конструктор» Bar сначала выполняет материал из Foo - sans f! - и , затем материал в определении Bar. Следовательно, f не определяется при построении chained.

Я называю ошибку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...