2013-05-08 9 views
7

precondizione effettivo di un sottotipo è creato combinando (utilizzando logico OR) precondizioni di un tipo di base e precondizioni di un sottotipo, il che rende il presupposto risultantemeno restrittivoNon può indebolire precondizioni e rafforzando postcondizioni violano anche Liskov principio di sostituzione?

Actual postcondition di un sottotipo viene creato combinando (utilizzando logico AND) postcondizioni di un tipo di base e post-condizione s di un sottotipo, il che rende la postcondizione risultantepiù restrittive

I seguenti sono esempi di rafforzare precondizioni e indebolimento postcondizioni, che di conseguenza violano LSP (Link):

  1. Supponi che la tua classe base funzioni con un membro int. Ora il tuo sottotipo richiede che int sia positivo. Questo è rafforzata precondizioni, e ora qualsiasi codice che funzionava perfettamente benissimo prima con interi negativi è rotto.

  2. Analogamente, assumere lo stesso scenario, ma la classe di base utilizzato per garantire che l'elemento sia positivo dopo essere stato chiamato. Quindi il sottotipo cambia il comportamento per consentire valori negativi. Il codice che opere sull'oggetto (e presuppone che il post-condizione è una positiva int) è ora rotto dal momento che la post-condizione non è accolto.

a) Perché non è anche considerata una violazione LSP quando metodo sostituito indebolisce precondizione, dal momento che questo metodo potrebbe utilizzare parametri che non sono accettabili per la contratti della base digitare. In quanto tale, non potremmo affermare che contratto del tipo di base è stata violata e di conseguenza LSP è stato inoltre violato?

b) Perché non viene anche considerata una violazione di LSP quando il metodo override rafforza la postcondizione, dal momento che i clienti che invocano questo metodo riceverà solo un sottoinsieme di possibili risultati del metodo originale. In quanto tale, non potremmo affermare che contratto del tipo di base è stata violata e di conseguenza LSP è stato inoltre violato?

Esempio:

Base classe postcondizione garanzie che il valore ritorno di un metodo sarebbe alla portata 1-10, ma poi il sottotipo cambia il postcondizione per consentire solo valore ritorno a essere all'interno dell'intervallo 2-9. Ora il codice che funziona sull'oggetto restituito da questo metodo (e presuppone che la postcondizione sia compresa nell'intervallo 1-10) sia interrotta poiché la postcondizione non viene confermata.

risposta

-1

Penso che il tuo esempio non supporti il ​​tuo punto nel senso seguente.

Nell'esempio negativo int, positivo, aggiungendo numeri negativi sebbene includa più possibilità indebolisce la garanzia della post-condizione. Il tuo esempio fa la stessa cosa. Sebbene garantisca un raggio più stretto, indebolisce comunque la garanzia della condizione post-condizione fornita dalla classe base.

La regola post-condizione in realtà dice:

Questa regola dice che il metodo sottotipo fornisce più rispetto al metodo supertipo: quando ritorna tutto ciò che il metodo supertipo avrebbe fornito è assicurata, e forse alcuni effetti aggiuntivi come bene (Sviluppo del programma in Java, p177)

Il tuo esempio non garantisce tutto ciò che il supertipo garantisce. Immagino che nel tuo esempio il rafforzamento significherebbe che il sottotipo garantisce che il ritorno int è in 1-10, inoltre garantisce che il ritorno int sia tra 2-9, non solo il secondo.

-1

Se il contratto di classe base per un metodo dice che invocarlo con un numero negativo genererà un'eccezione, allora qualsiasi classe derivata legittima dovrebbe lanciare la stessa eccezione se il suo metodo è passato un numero negativo. Se, tuttavia, il contratto di classe base dice semplicemente che un metodo non deve essere chiamato con numeri negativi senza specificare cosa accadrà se lo è, allora una classe base potrebbe fare qualsiasi cosa gli piaccia senza rompere quel contratto.

Mentre può sembrare inelegante avere condizioni in cui il comportamento di una classe non è specificato, l'aggiunta di funzionalità a una classe pur rimanendo compatibile verso l'alto in genere richiede la modifica di comportamenti non specificati in quelli specificati. In alcuni casi, un comportamento "non specificato" su una classe potrebbe essere "non riuscire a compilare", ma non è garantito che il codice che tenta di utilizzare tale membro non riuscirà mai a compilare. Ad esempio, se il contratto di una classe non fa menzione di un membro "Foo", il tentativo di utilizzare tale membro potrebbe causare un errore di compilazione, ma una versione futura della classe potrebbe definire Foo senza violare il suo contratto.

-2

Hai perfettamente ragione. Le precondizioni non possono essere indebolite. Ciò cambierebbe anche il comportamento del tipo di base. Per esempio:

class Base { void method(int x) { /* x: 1-100 allowed else exception */ } } 
class Weak: Base { void method(int x) { /* x: 1-1000 allowed else exception */ } } 
class Strong: Base { void method(int x) { /* x: 1-10 allowed else exception */ } } 

int Main() { 
    Base base = new Base(); 
    base.method(101-1000); // exception 

    Base base2 = new Weak(); 
    base2.method(101-1000); // ok 

    Base base3 = new Strong(); 
    base3.method(101-1000); // exception 
} 

LSP è chiaramente violata: classe debole per 101-1000 ok, ma Classe base per 101-1000 getta eccezione. Questo chiaramente non è lo stesso comportamento.

LSP si aspetta, l'insieme di numeri per la classe base può essere ampliato (rafforzato) in sottoclassi, ma nel programma principale l'insieme non verrà ampliato e quindi la sottoclasse con precondizioni più deboli può riempire le precondizioni della classe base .

Lo stesso vale per le post-condizioni nell'altro senso.

+1

Non ha senso confrontare il comportamento della classe base rispetto alla sottoclasse se si sta violando il contratto (1-100) della classe base in primo luogo. LSP si applica solo all'interno delle specifiche della classe base. Fuori specifica è un comportamento sconosciuto. – keyoxy

-1

LSP significa che si dovrebbe essere in grado di sostituire la classe base con la sottoclasse per i valori di input specificati. Non ha senso confrontare il comportamento della classe base rispetto alla sottoclasse quando si sta violando il contratto della classe base in primo luogo (non si ha a che fare con la vera sostituzione se lo si fa).

(violando il contratto è un comportamento noto, succede solo che l'approccio più comune è quello di generare un'eccezione.)

Per quanto riguarda il rafforzamento della postcondizione, non vedo il tuo punto, in realtà (?) Se il contratto sta specificando i valori 1-10, qualsiasi valore compreso tra 1 e 10 è de facto nella specifica, anche 2-9 o anche 3 sempre (?)

0

Ci scusiamo, ma si ha un errore logico nelle considerazioni.

Classe base postcondizione garantisce che il valore di ritorno di un metodo sarebbe nel range 1-10, ma poi il sottotipo cambia il postcondizione per consentire solo valore restituito per essere nell'intervallo 2-9.

Da codice funziona nel range 1-10 e varia 2-9 è in realtà nel range 1-10, rafforzando postcondizione dovrebbe essere mai un problema.

Stessa cosa con l'indebolimento delle precondizioni. Consentire al sottotipo di accettare un intervallo più ampio non sta infrangendo il comportamento del tipo di base. Poiché il comportamento è introdotto solo nel sottotipo e solo come precondizione per i metodi del sottotipo.

Problemi correlati