La mia osservazione è che molte persone usano impropriamente l'ereditarietà multipla senza lavorare attraverso le domande sul tipo di composizione.
L'esempio OO "classico" di un'auto porta a questo problema. Ad esempio, diremo che un'auto si divide nelle seguenti parti:
- è un veicolo
- ci sono gli pneumatici
- c'è un motore
- c'è uno chassis
- ci sono posti
- e così via ...
quindi definiremo una classe simile a questa:
public class Car : Vehicle, Tires, Engine, Chassis, Seats {}
Tutto bene, ma presenta alcuni problemi significativi con l'incapsulamento e costruttori / distruttori. E non rappresenta esattamente l'aspetto di un'auto nel mondo reale.
Se iniziamo a fare domande sulla composizione, vedremo alcune sfumature che all'inizio non erano ovvie.
- è un'auto un veicolo? (Sì)
- è un'auto un pneumatico o una serie di pneumatici? (no, ha un set di pneumatici)
- è un'auto un motore? (No)
- è un'auto un posto? (No)
- ecc.
Quindi ora la nostra classe può apparire in questo modo:
public class Car : Vehicle
{
public Tires tires; //ie, myCar _has_ a set of tires.
protected Engine engine;
private Chassis chassis;
protected Seats seats;
}
Che è anche tutto bene. Ma ora iniziamo a grattarci la testa e diciamo "sai, mi piacerebbe davvero che quando istanzio un'auto che debba avere pneumatici, un motore e un telaio."
Quindi ora possiamo trasformare gli pneumatici, il motore e lo chassis in interfacce e avremo la seguente classe. Sto prefiggendo le interfacce con "I" per rendere più chiara la distinzione.
public class Car : Vehicle, ITires, IEngine, IChassis
{
protected Seats seats;
}
Le interfacce sono come i contratti. Quando una classe implementa un'interfaccia, garantisce che fornirà determinati metodi e comportamenti.
E ora le cose vanno davvero bene. Il nostro modello dell'automobile riflette accuratamente la rappresentazione del mondo reale dello stesso oggetto, incluse alcune garanzie sulla somiglianza tra le due forme di cortesia delle interfacce. Abbiamo evitato i problemi icky che l'ereditarietà multipla può creare.
Questo non vuol dire che l'ereditarietà multipla sia sempre cattiva. Tuttavia, non è davvero necessario la maggior parte del tempo, motivo per cui linguaggi come Java e C # non consentono l'ereditarietà multipla.