I have a class that I’m trying to make extend DelayedInit:
class Foo extends DelayedInit {
// expensive initialisation code
}
However when I try to run sbt compile I get the error:
Foo needs to be abstract, since method delayedInit in trait DelayedInit of type (x: => Unit)Unit is not defined
My understanding is that by extending the DelayedInit trait any initialisation code should automatically be wrapped in a closure and run in the delayedInit method after initialisation is complete. However I’ve had a stab at googling and can’t seem to find an example of usage. What am I missing?
How
DelayedInitWorks and its Sample UsageDelayedInittrait provides the ability to control at which point initialisation code within a class or an object (but not a trait) is run.Any initialisation code within classes or objects (but not traits) that are inherited from
DelayedInitis passed by compiler during the initialisation to thedelayedInitmethod and then it’s up to you when you want to run it.delayedInitmethod is called automatically as part of the initialisation and running the code that is passed as a parameter straight away within the method is still running the code during the initialisation.Let’s start with a basic scenario:
Will print:
In fact,
delayedInitmethod will be called once for every class that inherits the trait within the class hierarchy. A slightly more complicated scenario:Will print:
Since
mainmethod is the first method to run once the initialisation is over, what we really want to do is to save all the initialisation code passed todelayedInitand run it later, probably from withinmain, since there is potentially more than one bit of code we could conveniently store it in aListBuffer(we need to keep appending to preserve the natural execution order). The code inside ‘Main` object could look something like this:However, there is a catch 22: because initialisation of
initfield is delayed along with every other initialisation statement there isn’t anyListBuffer[()=>Unit]object to preserve the initialisation code for later use!But, remember?
Let’s re-shuffle things a bit, move functionality that memorises the code for later use into
StoredInittrait that inherits directly fromDelayedInit:Will print:
Finally, why doesn’t
DelayedInittrait include a default implementation ofdelayedInitmethod?To keep the compiler hook de-coupled from the actual implementation of delayed initialisation behaviour. The desired behaviour will be different for console application and server-side component that has to work within a specific container.
trait App, however, inherits fromDelayedInitand provides default implementation for Scala applications.