https://kotlinlang.org logo
Title
n

Neil

06/27/2019, 9:16 AM
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

Pavlo Liapota

06/27/2019, 9:32 AM
Parent class constructor is always called first.
k

karelpeeters

06/27/2019, 9:34 AM
So the answer is: you can't.
n

Neil

06/27/2019, 9:35 AM
I see. As is the init{} block. So how can I do what I need?
k

karelpeeters

06/27/2019, 9:35 AM
😒imple_smile:
n

Neil

06/27/2019, 9:42 AM
:-(
What's the least-worst workaround?
j

Jonathan Mew

06/27/2019, 9:43 AM
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

Neil

06/27/2019, 9:49 AM
Something like the builder might be best, thanks @Jonathan Mew.
Is this limitation intended by design?
k

karelpeeters

06/27/2019, 10:11 AM
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

Neil

06/27/2019, 10:14 AM
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

karelpeeters

06/27/2019, 11:52 AM
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

Mike

06/27/2019, 1:31 PM
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

Neil

06/27/2019, 4:30 PM
@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

Mike

06/27/2019, 5:18 PM
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

Neil

06/27/2019, 5:35 PM
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

karelpeeters

06/27/2019, 5:35 PM
Why is that not just a constructor parameter then?
n

Neil

06/27/2019, 5:36 PM
User convenience.
m

Mike

06/27/2019, 5:37 PM
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

Neil

06/27/2019, 5:43 PM
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

karelpeeters

06/27/2019, 5:43 PM
Default constructor parameter?
n

Neil

06/27/2019, 5:47 PM
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!