Ereditarietà a carattere ontologico¶
Una delle motivazioni con cui il concetto di ereditarietà viene presentato (e spesso l'unico genere di esempio che lo riguarda) ha a che fare con entità che, nella realtà, sono dal punto di vista ontologico in una relazione di più specifico/meno specifico o di "è un" (is a), ossia in cui l'ereditarietà è vista dal punto di vista ontologico.
Uno degli esempi più classici è tratto dalla geometria e si basa sul fatto che le varie figure piane (cerchi, rettangoli, quadrati…) sono tutte esempi di un'entità più generica che è, appunto, la figura piana. In tale contesto si fa spesso l'esempio del quadrato come sottotipo di rettangolo (in simboli quadrato $\prec$ rettangolo): tutti i quadrati, infatti, sono a ben vedere dei rettangoli (che hanno la base uguale all'altezza), ma non è vero il viceversa.
Nell'ambito dei tipi di dato astratti però, abbiamo visto che l'estensione è di solito sviluppata nella direzione opposta: il rettangolo ha infatti un attributo in più (l'altezza) del quadrato (che è identificato dalla sola base).
Risulta molto naturale infatti scrivere il tipo Square
con un solo attributo
e definire per estensione il tipo Rectangle
Ma in questo modo la relazione di sottotipo Rectangle
$\prec$ Square
è l'opposto della relazione ontologica per cui quadrato $\prec$ rettangolo!
Si potrebbe certamente pensare che questa inversione sia fittizia e sia legata alla scelta implementativa; si potrebbe infatti pensare che è possibile ribaltare la direzione in cui un tipo estende l'altro pur di sovrascrivere i metodi mutazionali del rettangolo in modo che, nel caso del quadrato, adeguino la base qualora venga cambiata l'altezza.
Si potrebbe cioè pensare di porre Rectangle
come supertipo
con due metodi mutazionali per base e altezza, e implementare Square
per estensione, facendo attenzione a sovrascrivere i metodi mutazionali base
e height
in modo che mantengano coerenti base e altezza
Il principio di sostituzione¶
Immaginiamo ora di voler costruire un istogramma di rettangoli in cui i rettangoli aggiunti all'istogramma sono mantenuti in ordine crescente d'altezza. Supponiamo inoltre che per ragioni "tipografiche" sia sensato alterare la base dei rettangoli anche una volta che sono parte dell'istogramma (ad esempio, per restringerne l'ampiezza complessiva).
Evidentemente, ciò che accade se sostituissimo il sottotipo Square
al posto di Rectangle
il metodo changeBase
avrebbe l'effetto (inatteso) di modificare anche l'altezza, non preservando il contratto di Histogram
. Si consideri il seguente client
L'uso in hist1
mostra il comportamento inteso, ma non è così per quello di hist2
, come risulta dall'esecuzione del codice, che genera l'output
Come si nota, infatti, i rettangoli restano ordinati per altezza anche dopo il cambiamento della base (prime due righe), ma così non è per i quadarti, che, evidentemente, dopo il cambiamento di base hanno anche le altezze in ordine decrescente (ultime due righe).