Devo aggiungere funzionalità comuni ad alcune classi che condividono la stessa superclasse, preferibilmente senza gonfiare la superclasse. La catena di ereditarietà semplificata ha questo aspetto:
Element -> HTMLElement -> HTMLAnchorElement
Element -> SVGElement -> SVGAlement
Il metodo predefinito doSomething()
su Element
è non operativo per impostazione predefinita, ma esistono alcune sottoclassi che richiedono un'implementazione effettiva che richiede alcuni metodi e membri di istanze sottoposti a override aggiuntivi. Non riesco a mettere una piena implementazione di doSomething()
in Element
perché 1) è rilevante solo per alcune sottoclassi, 2) la sua implementazione ha un impatto sulle prestazioni e 3) dipende da un metodo che può essere sovrascritto da una classe nella catena ereditaria tra la superclasse e una sottoclasse, ad es SVGElement
nel mio esempio.
Specialmente a causa del terzo punto, volevo risolvere il problema usando una classe template, come segue (è una specie di decoratore per le classi):
struct Element {
virtual void doSomething() {}
};
// T should be an instance of Element
template<class T>
struct AugmentedElement : public T {
// doSomething is expensive and uses T
virtual void doSomething() override {}
// Used by doSomething
virtual bool shouldDoSomething() = 0;
};
class SVGElement : public Element { /* ... */ };
class SVGAElement : public AugmentedElement<SVGElement> {
// some non-trivial check
bool shouldDoSomething() { /* ... */ return true; }
};
// Similarly for HTMLAElement and others
Mi sono guardato intorno (nella già esistente (enorme) base di codice e su internet), ma non ho trovato frammenti di codice simili, per non parlare di una valutazione dell'efficacia e delle insidie di questo approccio.
Il mio design è la strada giusta da percorrere, oppure esiste un modo migliore per aggiungere funzionalità comuni ad alcune sottoclassi di una determinata superclasse?