Running code after subclass initialization
Sometimes you need to run some code after the subclass initialization - for example, if it is a library class that users extend and you need to check their configuration.
The simple solution will be simply to obligate user to call some method in your class after he is done, but it looks redundant, prone to error, and not beautiful overall.
It turns out that Scala has no obvious mechanism for this, so I needed to go through some hoops to achieve the needed effect.
My idea was to use the DelayedInit trait (which is deprecated now, sadly) in order to get the initialization bodies for the parent class and subclasses, then execute them in "delayedInit", and count the amount of times it executed. Since I can get the number of superclasses for any given class, I can just execute the after-init code when I've seen enough initialization bodies.
I wrapped this into a trait for easier reuse. Note that if your class extends some other non-trait, you'll need to override the afterInitLevel def.
The simple solution will be simply to obligate user to call some method in your class after he is done, but it looks redundant, prone to error, and not beautiful overall.
It turns out that Scala has no obvious mechanism for this, so I needed to go through some hoops to achieve the needed effect.
My idea was to use the DelayedInit trait (which is deprecated now, sadly) in order to get the initialization bodies for the parent class and subclasses, then execute them in "delayedInit", and count the amount of times it executed. Since I can get the number of superclasses for any given class, I can just execute the after-init code when I've seen enough initialization bodies.
I wrapped this into a trait for easier reuse. Note that if your class extends some other non-trait, you'll need to override the afterInitLevel def.
trait AfterInit extends DelayedInit {
def afterInit
def afterInitLevel = 1
private var initCount = 0
private def getInitNumber(clazz: Class[_]):Int =
if (clazz.getSuperclass == classOf[java.lang.Object]) 0 else getInitNumber(clazz.getSuperclass) + 1
final def delayedInit(x: => Unit) {
x
initCount += 1
if (getInitNumber(this.getClass) + afterInitLevel == initCount) afterInit
}
}
abstract class A(id:String) extends AfterInit {
def afterInit = println("Inited!")
}
class B extends A("BB") {
println("B inited!")
}
new B // prints "B inited!", "Inited!"
Comments
Post a Comment