Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instance of trait throws null pointer

Tags:

scala

Why does a null pointer exception occur in the code below?

object Test extends App{
    trait MyTrait[A]{ self =>
        val seq: Seq[A]
        val size = seq.size // null pointer here
    }

    val p = new MyTrait[Int]{
        val seq = Seq(1,2,3)
    }
}

If I change the size field to lazy then it's ok.

like image 641
Pengin Avatar asked Dec 12 '22 22:12

Pengin


2 Answers

Fields are initialized in the order they are mixed in--so first everything in the trait happens, and then the val is assigned to Seq(1,2,3) (since you're essentially mixing in an anonymous trait).

As you have discovered, lazy val is often a way out of this mess: you don't actually call seq.size until you need it, which is after you have populated the seq field.

like image 86
Rex Kerr Avatar answered Dec 14 '22 10:12

Rex Kerr


The style recommendation is to avoid vals in traits, in favor of defs and lazy vals, because of init order land mines.

Sample conversation: https://groups.google.com/forum/?fromgroups=#!topic/scala-user/nrOrjPOYmb0

like image 33
som-snytt Avatar answered Dec 14 '22 12:12

som-snytt