Supponiamo di avere la seguente gerarchia di classi:
class Object {
public:
virtual void update() {
// Update position
}
};
class Rocket : public Object {
public:
virtual void update() {
Object::update();
// Orientate towards target
}
};
class SparklingRocket : public Rocket {
public:
virtual void update() {
Rocket::update();
// Create sparkling particles
}
};
Per ovvi motivi questa non è una buona idea. Ad esempio, un erede di una delle classi potrebbe dimenticare di chiamare Base :: update () e il comportamento del programma sarebbe incompleto. A mio avviso, le funzioni che implementano un comportamento importante non dovrebbero essere rese virtuali, è meglio riservare un comportamento sostituibile.
Quindi, probabilmente cambieremo l'architettura in questo modo:
class Object {
public:
void update() {
// Update position
afterObjectUpdate();
}
protected:
virtual void afterObjectUpdate() {}
};
class Rocket : public Object {
protected:
virtual final void afterObjectUpdate() override {
// Orientate towards target
afterRocketUpdate()
}
virtual void afterRocketUpdate() {}
};
class SparklingRocket : public Rocket {
protected:
virtual final void afterRocketUpdate() {
// Create sparkling particles
afterSparklingRocketUpdate();
}
virtual void afterSparklingRocketUpdate() {}
};
Questo è praticamente quello che voglio:
- L'interfaccia pubblica di tutte le classi è solo l'aggiornamento non virtuale () - metodo
- Quando viene chiamato quel metodo, viene garantito che ogni aggiornamento () - "submethod" è chiamato
- Anche se l'unico erede si dimentica di chiamare un metodo afterUpdate (), la gerarchia è stabile dalla classe base in giù. In questo modo un'API potrebbe garantire la propria integrità mentre nel primo esempio di codice dovrebbe fare affidamento sull'utente per chiamare il metodo Base :: update ()
Non mi piace però una cosa: il nome di ogni classe fa parte del dopo ... Update () methodname. Mi sembra un codice per me.
Penso che l'obiettivo generale di mantenere le gerarchie di chiamate virtuali stabili non può essere così raro. Qual è la soluzione comunemente applicata che non ho ancora incontrato?