uraj uraj - 22 days ago 8
Scala Question

How to statically register callbacks in Scala?

In C++ one can implement a dispatcher-callback pattern with statically registered callbacks, thanks to the static members. In Scala, however, all objects are lazily initialized, so the code below doesn't really works as similar things in C++.

object Main {
var callbacks = List[()=>Unit]()
def main(args: Array[String]): Unit = {
println("hello")
callbacks.foreach { _() }
}
}
object A {
val callbackA = () => println("A")
Main.callbacks = callbackA::Main.callbacks
}
object B {
val callbackB = () => println("B")
Main.callbacks = callbackB::Main.callbacks
}
object C {
val callbackC = () => println("C")
Main.callbacks = callbackC::Main.callbacks
}


When I run this program, none of the callbacks are invoked, because objects A, B, and C are never initialized and the registrations are never executed. Is there is a way in Scala to correctly implement what I intend here?

Answer

You can use reflection to make a list of "all classes that implement trait MyCallback" and add them to a list, at program startup. You would have to define a trait, e.g.

sealed trait MyCallback {
    def callback: Unit
}

In the context of your example, objects A, B and C would extend MyCallback.

For the reflection code, see for instance Finding objects using scala's runtime reflection