randomstatistic randomstatistic - 21 days ago 7
Scala Question

Lazy assertions in a trait

I find I occasionally want to write an arbitrary assertion in a trait, or in some other place where the thing I want to make an assertion on is not yet fully defined.

trait Foo {
val aList: List[String]
val anotherList: List[String]

def printPairs = aList.zip(anotherList).foreach(println)

assert(aList.size == anotherList.size) // NullPointerException, because these references are undefined right now.
}


I suppose a generalization of what I'm looking for is a hook that (always) fires after the class is fully defined and instantiated, since this is the sort of check I'd generally put in a constructor.

Answer

You can do it using Early Definitions (search for it in the Scala Language Reference for more info) - with your trait exactly as you wrote it, you can extend it as follows:

class Bar(l1: List[String], l2: List[String]) extends {
  val aList = l1
  val anotherList = l2
} with Foo

Which would initiate the lists before calling the assert, therefore:

new Bar(List("a", "b"), List("c", "d")) // built successfully
new Bar(List("a", "b"), List("c", "d", "e")) // throws exception

Of course - it's not exactly what you asked for (a "hook" that's always called after construction), as any extending class would have to know which members must be overridden "early", but as far as I know that's the closest you can get.