Principio di Liskov: le sottoclassi possono avere invarianti più forti. Come potrebbe funzionare?

3

Conoscendo il principio di Liskov, comprendo che le precondizioni possono essere indebolite e le postcondizioni possono essere più forti nei sottotipi. Tuttavia, non capisco come gli invarianti possano essere più forti nel sottotipo?  Se la classe base dice per es. la velocità deve essere inferiore a 100 al tempo, quindi un sottotipo dice Velocità < 50, la sostituzione della base con il sottotipo può causare alcuni problemi oppure no? Voglio dire, se da qualche parte il codice funziona con la classe base e funziona alla velocità di 90, l'introduzione del sottotipo significa che non sarà valido.

Il codice e un testo possono essere trovati nelle diapositive 15 = 16:

link

    
posta Ezoela Vacca 26.01.2018 - 08:53
fonte

2 risposte

2

Il principio di sostituzione di Liskov afferma che è possibile sostituire l'implementazione della classe T senza alterare nessuna delle proprietà desiderabili di T. Nell'esempio si menziona una classe di base in cui la velocità deve essere sempre inferiore a 100 e in un'implementazione, la velocità deve sempre inferiore a 50.

Questa non è una violazione perché la classe base richiede solo che la velocità sia inferiore a 100 e che è presumibilmente soddisfatta a prescindere dal fatto che la classe derivata richieda che sia inferiore a 50 o se richiede che sia inferiore a 75.

In altre parole se la velocità è inferiore a 50, deve anche essere inferiore a 100 e quindi non vi è alcuna violazione. La violazione sarebbe se la classe derivata consentisse che la velocità superasse 100.

Sostituire un'istanza in cui la velocità è inferiore a 100 con un'altra che consente di superare la velocità di 200 comporterebbe la violazione del Principio di sostituzione di Liskov e delle leggi della strada!

    
risposta data 26.01.2018 - 10:37
fonte
2

La sostituibilità di Liskov non significa che puoi sostituire un oggetto di una sottoclasse per un oggetto di una superclasse e il tuo programma sarà ancora corretto . L'unica cosa che garantisce è che le promesse fatte dalla superclasse saranno onorate da tutte le sottoclassi .

Nel tuo caso, la superclasse ha promesso "La mia velocità non supererà i 100" e mantiene questa promessa. Anche la sottoclasse mantiene questa promessa.

La sottoclasse introduce anche una promessa nuova e più severa: " La mia velocità non supererà i 50" e onora anche questa promessa. Questo è possibile perché gli stati ammessi dalle nuove premesse sono un sottoinsieme ristretto degli stati consentiti dalla vecchia promessa.

La superclasse non onora questa nuova promessa, anzi non ne è nemmeno a conoscenza. Ciò significa che il suo comportamento sarà diverso dal comportamento della sottoclasse. Ovviamente, questo può influire sulla correttezza del programma - la sostituibilità non significa che qualsiasi classe in una gerarchia di classi è buona come l'altra.

Allora a che serve la sostituibilità di Liskov? È buono solo come il sistema di tipi nella tua lingua. Fa un buon lavoro rafforzando le pre e postcondizioni che il sistema di tipi nella tua lingua può esprimere. Ad esempio, una volta che dichiari un metodo che restituisce un unsigned int , puoi essere certo che non restituirà mai un valore negativo, e nessuno dei due avrà una sottoclasse . Ma probabilmente non è possibile esprimere "questo metodo trova la migliore classificazione dei valori di input vicini più vicini" nel sistema di tipi, pertanto l'LSP non può garantire la correttezza del programma in base all'ereditarietà. (Per essere onesti, quasi nessun formalismo può.)

    
risposta data 26.01.2018 - 09:58
fonte