My actual usage is in a embedded DSL (SpinalHDL), it use DelayedInit/onCreate to automaticaly build a component hierarchy from the user code execution:
//embedded DSL core
object Component{
val componentStack = mutable.Stack[Component]()
}
class Component extends OnCreate{
val children = ArrayBuffer[Component]()
val parent = Component.componentStack.head()
parent.children += this
Component.componentStack.push(this)
//Automatic callback after the whole object construction
def onCreate() = Component.componentStack.pop()
}
//User code
class UserSubComponent extends Component{
//behaviour code
}
class UserComponent extends Component{
//behaviour code
val subA = new UserSubComponent() //subA automaticaly know his parrent component via the componentStack, and it will automaticaly add itself to the UserComponent children list.
val subB = new UserSubComponent()
}
Some sort of DelayedInit replacement for scope management:
import db.Connection
@main def main():Unit = {
val c = new Connection()
//It is less error prone because nobody can forget to call method and do import.
//And it is more easy to write
c.execute{new{
setValue(2.ss)
}}
}
package db
class Statement(){
var value:String = "default value"
def execute():Unit = println(s"value=$value")
}
class StatementBuilder(given private val s:Statement){
//here it can be extensions, typeclasses
def (v:Int)ss: String = v.toString()
def setValue(v:String):Unit = s.value = v
}
class Connection{
def execute(buildStatement:(given Statement)=>StatementBuilder): Unit = {
//before advice
given s:Statement = new Statement()
//dsl statement
buildStatement
//after advice
s.execute()
}
}