How does a parent class execute code at the end of...
# announcements
n
How does a parent class execute code at the end of construction, after all the subclass' properties have been initialized and their init{} blocks run?
p
Parent class constructor is always called first.
k
So the answer is: you can't.
n
I see. As is the init{} block. So how can I do what I need?
k
simple smile
n
:-(
What's the least-worst workaround?
j
call into a method on the parent class at the end of each subclass' init? ­čśĽ
bit miserable, maybe something better exists
Use a builder class which does the finishing-up stuff in build()? MIght need to use composition depending what your descendant classes are like.
n
Something like the builder might be best, thanks @Jonathan Mew.
Is this limitation intended by design?
k
Wanting to run code after subclasses have been initialized means that your class depends on the subclasses, which leads to really brittle code.
Because "class depends on subclass" in the wrong way around.
n
It depends only as much as an abstract member creates a dependency
The function in the parent doesn't know anything about the subclass, but it expects the abstract properties to have been set by something in the subclass hierarchy, and that isn't done until after the parent's constructor and init.
k
Yes, but I was more talking about depending on possibly uninitialized state. It's the same reason you can't run code before calling the superconstructor, and why there are warnings for leaking
this
in the constructor.
m
Hmmm, then perhaps the parent should do lazy evaluation of the computations dependent on abstract properties? Of course assumes the properties don't change. If the property values do change, then you basically have a function anyway, right, and wouldn't be doing anything specific at init time? But w/o a concrete example, I'm guessing as to usage.
n
@karelpeeters agreed, that's part of my request, I'd like something that is called after the full hierarchy's state has been initialized. @Mike yes a lazy delegate might work but would make the code quite messy. No the values don't change.
m
Actually, why is it an abstract property rather than a property of the parent directly? If it was a property of the parent, it would be available in init of parent. If this doesn't work, then I wonder if you don't quite have the right design/relationship between parent and children. But again, a lot of guess work here.
n
It's a configuration property in the parent class. init() does different things depending on the value. For convenience I want to extend the class with child classes which set that property to different values.
k
Why is that not just a constructor parameter then?
n
User convenience.
m
Agreed. This is feeling like the wrong abstraction or class hierarchy depending on what changes. Are the children really the parent type or is this an attempt to reduce code duplication?
n
It's the parent type with a different configuration... I think!? A TextField can be a password field or not. I'd rather default it to false because that's 99% of the usage, and provide a PasswordTextField which extends it but sets that to true.
k
Default constructor parameter?
n
Oh ok and then hardcode it to true when the child's constructor delegates to the parent's constructor. That should work. Thanks!
I didn't do that because I didn't want to expose the property publicly... But I guess that isn't terrible!