Questo è un articolo molto interessante.
Principio di apertura / chiusura
La definizione di una sottoclasse non infrange il principio di apertura / chiusura , poiché significa "< em> apri per estensione / chiudi per modifica ". Quindi:
- Si può perfettamente aggiungere
Penguin
sottoclasse per estendere Bird
- Ma cambiare l'interfaccia della classe
Bird
per aggiungere il supporto per gli uccelli che non possono volare è una modifica definitiva.
La classe Bird è stata viziata dall'inizio
Che cosa ci mostra l'esempio? Un caso molto pratico su come gestire un design imperfetto. E se il design non è praticabile, devi cambiarlo.
La classe Bird
era difettosa sin dall'inizio, perché non teneva conto del fatto che ci sono uccelli che non possono volare, sia l'intera classe Penguin
o una singola istanza di injuredBird
.
La classe è ancora più difettosa di quanto sembri. Poiché tutti gli uccelli hanno intervalli di altitudine: martin pescatori possono avere un'altitudine leggermente negativa sotto l'acqua. E nessun uccello non può volare nella stratosfera: alcune specie possono volare fino a 11.300 km, mentre altre sono limitate a 8.000. E Penguins
sono limitati tra 0 e 0 sopra il terreno (in realtà possono immergersi, quindi è consentita anche l'altitudine negativa.
Principio di sostituzione di Liskov in tutto questo?
Osservando il codice di esempio, l'aggiunta di Penguin
all'originale Bird
non è in effetti un problema in base al LSP , perché non viene fatta alcuna promessa sul risultato di setAltitude()
.
L'LSP ci dice che:
Le precondizioni - non possono essere rafforzate.
Le postcondizioni - non possono essere indebolite. Non si sostiene che l'altitudine sarà impostata sul valore fornito, quindi non c'è alcun indebolimento. Se il post-condono è che il nuovo valore dell'altitudine è compreso tra 0 e il valore fornito, l'estensione corrisponderà alle regole lasciando l'altitudine invariata. Btw.us, questa post-condizione consentirebbe anche
injuredBird
e newBornBird
.
Gli invarianti - devono essere preservati.
- il vincolo cronologico deve essere garantito Ciò implica che lo stato e il comportamento di
Bird
dipendono solo dall'utilizzo della sua interfaccia definita. Ad esempio, Penguin
non potrebbe avere nessun altro metodo che cambierebbe l'altitudine senza fare affidamento su setAltitude()
.