Penso che ci siano alcuni fattori che non sono ancora stati menzionati.
Prima di tutto, almeno in "OOP puro" (ad esempio Smalltalk) in cui tutto è un oggetto, devi distorcere la tua mente in una configurazione piuttosto innaturale per pensare a un numero (per un solo esempio) come un oggetto intelligente anziché solo un valore - poiché in realtà, 21
(ad esempio) è davvero solo un valore. Ciò diventa particolarmente problematico quando da un lato ti viene detto che un grande vantaggio di OOP è modellare la realtà più da vicino, ma inizi prendendo ciò che assomiglia moltissimo a una visione ispirata all'LSD anche delle parti più elementari e ovvie di realtà.
In secondo luogo, l'ereditarietà in OOP non segue da vicino neanche i modelli mentali della maggior parte delle persone. Per la maggior parte delle persone, classificare le cose in modo più specifico non ha nulla vicino alle regole assolute necessarie per creare una gerarchia di classi che funzioni. In particolare, creare un oggetto class D
che eredita da un altro class B
significa che gli oggetti di class D
condivisione condividono assolutamente, positivamente tutte le caratteristiche di class B
. class D
può aggiungere nuove e diverse caratteristiche proprie, ma tutte le caratteristiche di class B
devono rimanere intatte.
Al contrario, quando le persone classificano le cose mentalmente, in genere seguono un modello molto più flessibile. Ad esempio, se una persona stabilisce alcune regole su ciò che costituisce una classe di oggetti, è abbastanza tipico che quasi ogni regola possa essere infranta fintanto che ne seguono abbastanza altre. Anche le poche regole che non si possono veramente infrangere possono quasi sempre essere "allungate" un po 'comunque.
Solo per esempio, considera "auto" come una classe. È abbastanza facile vedere che la stragrande maggioranza di ciò che la maggior parte della gente pensa come "auto" ha quattro ruote. La maggior parte delle persone, tuttavia, ha visto (almeno una foto di) un'auto con solo tre ruote. Alcuni di noi dell'età giusta ricordano anche una o due macchine da corsa dei primi anni '80 (circa) con sei ruote - e così via. Questo ci lascia sostanzialmente con tre scelte:
- Non affermare nulla su quante ruote ha un'auto, ma questo tende a dare per scontato che sarà sempre 4 e che il codice probabilmente si romperà per un altro numero.
- Afferma che tutte le auto hanno quattro ruote e classifica quelle altre come "non auto", anche se sappiamo che lo sono davvero.
- Progetta la classe per consentire la variazione del numero di ruote, per ogni evenienza, anche se ci sono buone possibilità che questa capacità non sarà mai necessaria, utilizzata o testata correttamente.
L'insegnamento di OOP si concentra spesso sulla costruzione di enormi tassonomie - ad esempio, frammenti di quella che sarebbe una gigantesca gerarchia di tutta la vita conosciuta sulla terra, o qualcosa in quell'ordine. Ciò solleva due problemi: in primo luogo, tende a condurre molte persone a concentrarsi su enormi quantità di informazioni che sono assolutamente irrilevanti per la domanda in corso. A un certo punto ho visto una discussione piuttosto lunga su come modellare le razze di cani e se (per esempio) "barboncino in miniatura" debba ereditare da "barboncino a grandezza naturale", o viceversa, o se ci dovrebbe essere una base astratta "Barboncino "classe, con" barboncino a grandezza naturale "e" barboncino in miniatura "che ereditano entrambi. Ciò che tutti sembravano ignorare era che l'applicazione doveva occuparsi di tenere traccia delle licenze per cani,
In secondo luogo, e quasi importante, porta a concentrarsi sulle caratteristiche degli articoli, invece di concentrarsi sulle caratteristiche che sono importanti per il compito da svolgere. Porta a modellare le cose così come sono, dove (la maggior parte delle volte) ciò che è veramente necessario è costruire il modello più semplice che soddisferà le nostre esigenze e usare l'astrazione per adattarsi al necessario sottoclassi per adattarsi all'astrazione che abbiamo costruito.
Infine, ripeto: stiamo lentamente seguendo lo stesso percorso intrapreso dai database nel corso degli anni. I primi database seguivano il modello gerarchico. Oltre a concentrarsi esclusivamente sui dati, questa è una singola eredità. Per un breve periodo, alcuni database hanno seguito il modello di rete, sostanzialmente identico all'ereditarietà multipla (e visti da questo punto di vista, interfacce multiple non sono abbastanza diverse dalle classi di base multiple da notare o preoccuparsi).
Molto tempo fa, tuttavia, i database convergevano in gran parte sul modello relazionale (e anche se non sono SQL, a questo livello di astrazione anche i database "NoSQL" attuali sono relazionali). I vantaggi del modello relazionale sono sufficientemente noti che non mi preoccuperò di ripeterli qui. Noterò solo che l'analogo più vicino al modello relazionale che abbiamo nella programmazione è la programmazione generica (e scusate, ma nonostante il nome, i generici Java, per esempio, non si qualificano davvero, sebbene siano un piccolo passo nel giusta direzione).