scala - Compiler complains about class that extends DelayedInit not defining delayedInit method -
i have class i'm trying make extend delayedinit
:
class foo extends delayedinit { // expensive initialisation code }
however when try run sbt compile
error:
foo needs abstract, since method delayedinit in trait delayedinit of type (x: => unit)unit not defined
my understanding extending delayedinit
trait initialisation code should automatically wrapped in closure , run in delayedinit
method after initialisation complete. i've had stab @ googling , can't seem find example of usage. missing?
how delayedinit
works , sample usage
delayedinit
trait provides ability control @ point initialisation code within class or object (but not trait) run.
any initialisation code within classes or objects (but not traits) inherited delayedinit
passed compiler during initialisation delayedinit
method , it's when want run it.
delayedinit
method called automatically part of initialisation , running code passed parameter straight away within method still running code during initialisation.
let's start basic scenario:
object main extends delayedinit { println (" initialisation of main object") override def delayedinit (body: => unit) { println("delayedinit") body } def main (args: array[string]) { println("main method") } }
will print:
delayedinit initialisation of main object main method
in fact, delayedinit
method called once every class inherits trait within class hierarchy. more complicated scenario:
abstract class myapplication extends delayedinit { println (" initialisation of myapplication class") } object main extends myapplication { println (" initialisation of main object") override def delayedinit (body: => unit) { println("delayedinit") body } def main (args: array[string]) { println("main method") } }
will print:
delayedinit initialisation of myapplication class delayedinit initialisation of main object main method
since main
method first method run once initialisation over, want save initialisation code passed delayedinit
, run later, within main
, since there potentially more 1 bit of code conveniently store in listbuffer
(we need keep appending preserve natural execution order). code inside 'main` object this:
private val init = new scala.collection.mutable.listbuffer[()=>unit] override def delayedinit (body: => unit) { println("delayedinit") init += (()=>body) // result in nullpointerexception } def main (args: array[string]) { println("main method") (code <- init) code () }
however, there catch 22: because initialisation of init
field delayed along every other initialisation statement there isn't listbuffer[()=>unit]
object preserve initialisation code later use!
but, remember?
any initialisation code within classes or objects (but not traits) inherited
delayedinit
passed compiler during initialisationdelayedinit
method...
let's re-shuffle things bit, move functionality memorises code later use storedinit
trait inherits directly delayedinit
:
trait storedinit extends delayedinit { println ("initialisation of storedinit trait") private val init = new scala.collection.mutable.listbuffer[()=>unit] override def delayedinit (body: => unit) { println("delayedinit") init += (()=>body) } def initialise () { (code <- init) code () } } // extend storedinit instead of delayedinit abstract class myapplication extends storedinit { println (" initialisation of myapplication class") } object main extends myapplication { println (" initialisation of main object") def main (args: array[string]) { println("main method") initialise() // perform delayed initialisation } }
will print:
initialisation of storedinit trait delayedinit delayedinit main method initialisation of myapplication class initialisation of main object
finally, why doesn't delayedinit
trait include default implementation of delayedinit
method?
to keep compiler hook de-coupled actual implementation of delayed initialisation behaviour. desired behaviour different console application , server-side component has work within specific container.
trait app
, however, inherits delayedinit
, provides default implementation scala applications.
Comments
Post a Comment