2011-01-15 21 views
5

Rozważmy następujący (uproszczony) Przykład:NullPointerException podczas dostępu nadpisane val w abstrakcyjne konstruktora

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 } 
} 

i obejrzeć go trzask:

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>) 
     .... 

Jeśli jednak stawiamy chained w konkretnej klasie:

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 
} 

Działa zgodnie z oczekiwaniami:

scala> val foo = new Foo 
foo: Foo = [email protected] 

Muszę przyznać, że absolutnie nie mam pojęcia, co się tutaj dzieje. Pluskwa? (To jest na Scala 2.8.1.)

+0

Zobacz to pytanie, aby uzyskać rozwiązanie/obejść: http://stackoverflow.com/questions/4712468/in-scala-what-is-an-early-initializer – Raphael

Odpowiedz

5

"Dlaczego mój abstrakt lub zastępuje wartość val null?" https://github.com/paulp/scala-faq/wiki/Initialization-Order

+0

Dzięki. "lazy val spained ..." rozwiązuje to. –

+0

A: Link jest teraz 404, B: niektórzy ludzie chcą uniknąć leniwych valsów – samthebest

+0

Link jest teraz [tutaj] (http://docs.scala-lang.org/tutorials/FAQ/initialization-order.html) i jest słaby ćwicz, aby odpowiedzieć za pomocą linków. – nedim

0

Zgaduję: To jest optymalizacja wykonana w czasie kompilacji. Kompilator rozpoznaje, że zastępujesz f w Bar. Dlatego "konstruktor" z Bar wykonuje najpierw rzeczy z Foo - sans f! - i następnie rzeczy w definicji Bar. Dlatego też f nie jest zdefiniowany podczas konstruowania chained.

Wzywam błąd.

Powiązane problemy