Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to initialize trait's vals in subtrait?

Tags:

scala

traits

I tried using an abstract val in a trait to initialize another value. I got a NullPointerException. I boiled the behaviour down to a minimal test case:

trait MessagePrinter {
  val message: String
  println(message)
}

class HelloPrinter extends MessagePrinter {
  val message = "Hello World"
}

val obj = new HelloPrinter()
println(obj.message)

This little program yields the following result:

null
Hello World

I was under the impression that a val may never change. Is this expected behaviour or is it a compiler bug? How can I work around this issue and print Hello World during initialization?

like image 570
Richard Avatar asked Jan 05 '15 14:01

Richard


2 Answers

By section 5.1 of the Scala specification, super classes are initialized first. Even though vals cannot normally be reinstantiated, they do start with a default initial value during construction. You can either use def, which has different semantics:

trait MessagePrinter {
   def message: String
   println(message)
}

class HelloPrinter extends MessagePrinter {
   def message = "Hello World"
}

Or you might consider switching things around like so:

class HelloPrinter extends { val message = "Hello World" } with MessagePrinter 

In which case the super classes are evaluated in order, so that the MessagePrinter initialization should work as desired.

like image 61
Ben Reich Avatar answered Oct 24 '22 20:10

Ben Reich


You should use def in both cases.

One of the sources describing this behaviour is "Scala Puzzlers" Puzzler 4:

The following rules control the initialization and overriding behavior of vals:

  1. Superclasses are fully initialized before subclasses.
  2. Members are initialized in the order they are declared.
  3. When a val is overridden, it can still only be initialized once.
  4. Like an abstract val, an overridden val will have a default initial value during the construction of superclasses.
like image 32
user5102379 Avatar answered Oct 24 '22 19:10

user5102379