Mi è sempre piaciuta l'idea di avere un'ereditarietà multipla supportata in una lingua. Molto spesso però è intenzionalmente dimenticato e la presunta "sostituzione" è un'interfaccia. Le interfacce semplicemente non coprono tutte le stesse caratteristiche dell'eredità multipla a terra e questa restrizione può occasionalmente portare a un codice più completo.
L'unico motivo fondamentale che ho mai sentito per questo è il problema dei diamanti con le classi base. Non posso accettarlo. Per me, si tratta di un sacco di cose del tipo: "Beh, è possibile per rovinarlo, quindi è automaticamente una cattiva idea." Però puoi rovinare tutto in un linguaggio di programmazione, e intendo qualsiasi cosa. Non riesco a prenderlo sul serio, almeno non senza una spiegazione più approfondita.
Il solo fatto di essere a conoscenza di questo problema è il 90% della battaglia. Inoltre, penso di aver sentito qualcosa di anni fa in merito a un lavoro generale che comportava un algoritmo di "busta" o qualcosa del genere (questo suona un campanello, chiunque?).
Riguardo al problema dei diamanti, l'unico problema potenzialmente reale che riesco a pensare è se stai cercando di usare una libreria di terze parti e non riesci a vedere che due classi apparentemente non correlate in quella libreria hanno una classe base comune, ma oltre alla documentazione, una semplice funzione linguistica potrebbe, diciamo, richiedere che tu dichiari specificatamente il tuo intento di creare un diamante prima che ne venga compilato uno per te. Con una tale caratteristica, qualsiasi creazione di un diamante è intenzionale, spericolata o perché non si è a conoscenza di questa trappola.
In modo che tutto sia detto ... C'è qualche motivo reale che la maggior parte delle persone odia l'eredità multipla, o è tutto solo un po 'di isteria che causa più danni che benefici? C'è qualcosa che non vedo qui? Grazie.
Esempio
Car estende WheeledVehicle, KIASpectra estende Car ed Electronic, KIASpectra contiene Radio. Perché KIASpectra non contiene Electronic?
-
Perché è un dispositivo elettronico. L'ereditarietà rispetto alla composizione dovrebbe sempre essere una relazione is-a vs. una relazione has-a.
-
Perché è un dispositivo elettronico. Ci sono fili, circuiti stampati, interruttori, ecc. Tutto su e giù per quella cosa.
-
Perché è un dispositivo elettronico. Se la tua batteria si spegne in inverno, ti trovi nei guai come se tutte le tue ruote fossero improvvisamente scomparse.
Perché non usare le interfacce? Prendi # 3, per esempio. Non voglio scriverlo più e più volte, e io veramente non voglio creare una classe di helper proxy bizzarra per fare questo:
private void runOrDont()
{
if (this.battery)
{
if (this.battery.working && this.switchedOn)
{
this.run();
return;
}
}
this.dontRun();
}
(Non stiamo valutando se l'implementazione sia buona o cattiva.) Puoi immaginare come possano esserci diverse di queste funzioni associate a Electronic che non sono correlate a nulla in WheeledVehicle, e viceversa.
Non ero sicuro se accontentarmi di quell'esempio o meno, dato che lì c'è spazio per l'interpretazione. Potresti anche pensare in termini di Plane extending Vehicle e FlyingObject e Bird extending Animal e FlyingObject, o in termini di un esempio molto più puro.