Hello again.
I think we can condense the issues raised in the thread so far down to:
- What purpose would this feature serve in the face of design/pattern-based
alternatives? - In what order should the constructor(s) be called?
- How to approach overriding these constructors if necessary?
- How would arguments to the constructor be treated?
My current thoughts on these:
- What purpose would this feature serve in the face of
design/pattern-based alternatives?
Less importantly, as hinted at previously in the thread, the proposed
approach offers slightly less complexity in the absense of any existing
framework e.g. the aforementioned Template Method pattern.
The main things I'd note are that, in a situation where the subclass is
offered the option by an underlying design to have some
before/init/after()-like methods for their startup code, a) it's
unnatural/counter-intuitive to say, "don't use the language-provided
constructor mechanism here, but use this particular implementation's
arbitrary nomenclature instead"
and
b) it's slightly restrictive, as you then have less options for method
names that you may have wanted for another use.
In summary, I feel the proposed approach would offer a "universal" solution
to the problem, rather than requiring that developers implement their own
solutions on an ad hoc basis; and then when moving to another project, have
to acclimatise to another developer's particular solution and nomenclature.
- In what order should the constructor(s) be called?
When I was considering this new feature, the user I had in mind is someone
who just wants to ensure their constructor is called one way or another,
but most likely to be called as a priority. However, it probably would be
wise to plan for more flexibility being desired.
As touched upon, unfortunately more keywords may be required to resolve
this. "before" and "after" would be a good starting point, with the
addition of (for demonstration purposes only) "alpha" and "omega" and
having the following behavior:
-
"before" constructors are called before their immediate parent.
-
"after" constructors are called after their immediate parent.
-
"alpha" constructors are called in a "first come first served" cascading
manner i.e. starting from the parentless super. -
"omega" constructors are called in the opposite order as alpha
constructors.
There could also be a fifth keyword which would hint to the compiler that
the constructor can be "trusted" to call super, which would effectively
disable the before/after functionality and allow the child class more
flexibility in where and how the parent constructor gets called.
It could also be the case that, if an "after" constructor is called
directly using parent::__construct(), that constructor is taken out of the
call queue.
- How to approach overriding these constructors if necessary?
I'll admit that I'm struggling with this one. There could perhaps be a
keyword to indicate that the subclass' constructor overrides all other
constructors, with the ability for it to call any supers' constructors
directly. e.g (syntax for demonstration purposes only):
class C extends B
{
public function overrides __construct()
{
super::B::__construct();
super::A::__construct();
}
}
Or simply the ability to specify which super to override:
class C extends B
{
public function overrides B::__construct()
{
}
}
- How would arguments to the constructor be treated?
My current thinking is, arguments should be passed to all constructors, but
the subclass constructor(s) shouldn't be required to receive them in the
method declaration i.e. __construct() is allowed regardless of the super's
accepted arguments.
If a constructor in the chain wishes to alter the arguments passed along,
it can do so using the override method, such as the one outlined above.
x. Closing notes.
A question to those who have knowledge of languages and patterns that
implement this functionality: How do those solutions answer the above 4
questions?