I'm working on a large software, that heavily relies on the call super anti-pattern.
Basically, an interface defines an init()
virtual method that is then overridden in every classes that inherits it.
When init()
is called on the class, EVERY overloaded init
methods are cascaded, from the base class to the top daughter class, and all in between.
But the user HAS to call its direct parent's init()
method in its own, which results in code like this:
class myClass : public Base
{
virtual void init()
{
Parent::Init() // often forgotten, or misplaced by the developer
// Do some init stuff
}
}
An alternative to this is usually to use delegates. The Base class has stuff to do in init
, that is declared final
in Base, and delegates part of it to an onInit()
method that inheriting classes should override. But this does not cascade the calls to all parent classes as I'd like it to.
The alternative I've first implemented is a variant of the delegate approach. Both daughter classes and Base implement a onInit()
and a init()
method.
init()
calls Parent::init()
followed by a call to onInit()
on itself, and is auto-generated using template meta-programming & macros.
and onInit()
contains the class-specific code.
# define DELEGATE(T, Parent) \
void init() override { Parent::init(); T::onInit(); }
struct Base
{
virtual void init() { Base::onInit(); }
virtual void onInit() {}
};
struct A : public Base
{
DELEGATE(A, Base)
void onInit() override { /* MyCustom code for A */ }
};
struct B : public A
{
DELEGATE(B, A)
void onInit() override { /* MyCustom code for B */ }
};
This works pretty well.. except that multiple inheritance becomes a mess, and even if handled, diamond inheritance causes issues with duplicated calls.
Which leaves me wondering: I can't be the only person looking for a design pattern solving my issue, and the stackoverflow community must know about it :)
Have you ever encountered a design pattern for this? I'm really looking forward to your ideas!