Chiedete perché, come se il se sia deciso. Consideriamo le tue supposizioni:
Why is inheritance generally viewed as a bad thing by OOP proponents
Non sono d'accordo con la premessa della domanda. L'ereditarietà non è generalmente considerata cattiva, è vista come abusata e abusata.
I modelli di progettazione GoF non dicono nulla di negativo.
Vediamo cosa dicono in effetti i Pattern Design di GoF ...
- p20 - Nella discussione su
Favor composition over inheritance
, che Eredità e composizione degli oggetti lavorano quindi insieme .
- p22 - La composizione degli oggetti ti consente di modificare il comportamento che viene composto in fase di esecuzione, ma richiede anche l'indirizzamento indiretto e può essere meno efficiente.
- p25 - ... d'altra parte, l'uso intensivo della composizione degli oggetti può rendere i disegni più difficili da capire.
E così via. Ora, ci sono anche molti aspetti negativi dell'eredità che potrei citare, ma il punto è che GoF non pretende che l'eredità sia cattiva e insegna chiaramente i pro ei contro di varie tecniche. Cosa significa favour
in questo contesto? Non rendere l'eredità la tua prima scelta. Un po 'come non rendere il piede di porco la tua prima scelta, prova prima la chiave.
Per quanto riguarda l'ereditarietà, esistono due tipi principali: ereditarietà di classe e ereditarietà dell'interfaccia (sottotipizzazione). Entrambi sono appropriati per modelli particolari, ma quest'ultimo è diventato favorevole da quando è stato pubblicato GoF. Se stavi imparando l'OOP nei primi anni '90, sapresti del Metodo Booch e del Metodo Rumbaugh, ma oggi ne senti poco. Eppure stavano insegnando a una generazione di programmatori C ++ (e Java) ad ereditare e scavalcare. Ma lo stato dell'arte è andato avanti. Abbiamo, attraverso l'esperienza collettiva, scoperto che l'accoppiamento libero si trova davvero attraverso l'uso di interfacce e iniezione di dipendenza, e non semplicemente usando l'incapsulamento.
Il problema con l'ereditarietà è troppi I programmatori "OO" pensano ai problemi prima come potenziali soluzioni di ereditarietà. L'ereditarietà è un concetto concreto che le persone capiscono rapidamente all'inizio, così tante persone si attaccano a questo e non crescono mai molto di più come modellisti di sistemi. Quando tutto in un sistema è incuneato in una gerarchia di ereditarietà e il codice viene riutilizzato dall'ereditarietà della classe, si ottengono risultati disastrosi e i benefici di OO sono superati dalla lotta effettiva con la stessa gerarchia. Ho visto molti progetti, e sono stato responsabile per alcuni di me stesso, che hanno trascorso più tempo a lottare su un'enorme gerarchia che a mantenere le interfacce del sottosistema. Questo è un segno di abuso di ereditarietà.
Ma a parte questo, l'eredità è inestimabile per realizzare molte cose buone. Il polimorfismo (in particolare il polimorfismo del sottotipo) è uno strumento molto potente e la distribuzione singola e doppia è la chiave per modelli come il pattern Visitor. L'ereditarietà dell'interfaccia è la chiave per progettare interfacce, non implementazioni. Le classi o le interfacce astratte sono utili solo con l'ereditarietà.
Se il tuo amico pensa che "favorire la composizione sull'eredità" è un mantra per evitare del tutto l'eredità, si sbaglia e non capisce il concetto di un set di strumenti completo.
Sembra che non abbia effettivamente letto GoF. Se ha affermato di leggerlo, sembra che abbia frainteso e dovrebbe leggerlo di nuovo.