Præsentation er lastning. Vent venligst

Præsentation er lastning. Vent venligst

FEN 2013-05-19KbP/seminar3: subcontracts1 Kontraktbaseret programmering Seminar 3 Kontrakter og arv Underleverandørsyn Substitutionsprincippet Guarded.

Lignende præsentationer


Præsentationer af emnet: "FEN 2013-05-19KbP/seminar3: subcontracts1 Kontraktbaseret programmering Seminar 3 Kontrakter og arv Underleverandørsyn Substitutionsprincippet Guarded."— Præsentationens transcript:

1 FEN 2013-05-19KbP/seminar3: subcontracts1 Kontraktbaseret programmering Seminar 3 Kontrakter og arv Underleverandørsyn Substitutionsprincippet Guarded postcondition

2 FEN 2013-05-19KbP/seminar3: subcontracts2 Underleverandørsyn •Kontraktmæssigt kan en subklasse betragtes som en underleverandør: –Superklassen har indgået en kontrakt med en klient –Superklassen overdrager kontrakten til en underleverandør –Subklassen tager superklassen plads og skal i forhold til klienter opfylde samme kontrakt

3 FEN 2013-05-19KbP/seminar3: subcontracts3 Fig. 6.1 i DbC. Figur fjernet pga. Copyright

4 FEN 2013-05-19KbP/seminar3: subcontracts4 Kontrakt class Courier{ //INVARIANT: forsikring >= 100,000 public void deliver(…); //PREpakkevægt <= 5 kg //POSTleveringstid<= 3 timer }

5 FEN 2013-05-19KbP/seminar3: subcontracts5 Arv og polymorfi •Princip: –I OOPLs kan objekter af en subklasse anvendes, hvor der forventes en forekomst af superklassen –Alt arves – også specifikation, dvs. subklassen overtager forfaderens kontrakt. –Hvis der ændres i kontrakten, så skal substitutionsprincippet overholdes. (”Underleverandør” eller ”subcontractor”)

6 FEN 2013-05-19KbP/seminar3: subcontracts6 Substitutionsprincippet (Babara Liskov, OOPSLA ’87) Man skal altid kunne substituere en forekomst af en afledt klasse ind, hvor der ventes en forekomst af baseklassen. (”Behavioral subtyping”)

7 FEN 2013-05-19KbP/seminar3: subcontracts7 Ændring af kontrakter •Substitutionsprincippet: –Arvingen skal mindst overholde forfaderens kontrakt, dvs. •prebetingelser må ikke strammes •postbetingelser må ikke afsvækkes –Hvis der ændres i kontrakten, så skal substitutionsprincippet overholdes.

8 FEN 2013-05-19KbP/seminar3: subcontracts8 Ny kontrakt //Ny kontrakt: class DifferentCourier extends Courier{ //INVARIANT: forsikring>= 200,000 public void deliver(…); //PREpakkevægt <= 8 kg //POSTleveringstid<= 2 timer } Kan klienter leve med denne kontrakt i stedet for den oprindelige? //Oprindelig kontrakt: class Courier{ //INVARIANT: forsikring >= 100,000 public void deliver(…); //PREpakkevægt <= 5 kg //POSTleveringstid<= 3 timer }

9 FEN 2013-05-19KbP/seminar3: subcontracts9 Substitutionsprincippet class A { //INVARIANT I public void pip(){}; //PRE p //POST q }; p  p’ dvs. hvis A.pip()’s PRE er opfyldt, så er B.pip()’s det også q’  qdvs. resultatet af B.pip() opfylder mindst samme betingelser som resultatet af A.pip() I´  I hvis den nye invariant er opfyldt, så er den gamle også class B extends A { //INVARIANT I’ public void pip(){}; //PRE p’ //POST q’ };

10 FEN 2013-05-19KbP/seminar3: subcontracts10 Eksempel: public class Shape{ private int x,y; // figurens position private Colour color; //figurens farve //øvrige attributter public void MoveTo(int newX, int newY){ //PRE: 0 <= newX <= maxX AND 0 <= newY <= maxY, // hvor maxX og maxY angiver vinduets maksimum // POST: x'=newX AND y'=newY } public virtual float Area(){ //PRE: none //POST: Area'= figurens areal med 4 betydende cifre // beregnet efter en eller anden tilnærmet metode} } }//end Shape public class Circle: Shape{ private int r; //radius - x, y //og color arves public override float Area(){ } //øvrige operationer - MoveTo() arves }//end circle Hvad må vi gøre med Area()? Hvad må vi gøre med MoveTo()?

11 FEN 2013-05-19KbP/seminar3: subcontracts11 Dictionary: public interface Dictionary { /*@ invariant count()>=0; @*/ // Basic queries public /*@ pure @*/ int count(); /*@ ensures (count()==0) ==> (!\result); @*/ public /*@ pure @*/ boolean has(Object key); /*@ requires has(key); @*/ public /*@ pure @*/ Object valueFor(Object key); // Derived queries /*@ ensures \result == (count()==0); @*/ public boolean isEmpty(); // Commands /*@ requires !has(key); @ ensures has(key); @ ensures valueFor(key)==value; @ ensures count()==(\old(count())+1); @*/ public void put(Object key, Object value); /*@ requires has(key); @ ensures !has(key); @ ensures count()==(\old(count())-1); @*/ public void remove(Object key); }

12 FEN 2013-05-19KbP/seminar3: subcontracts12 Designvalg /*@ requires !has(key); @ ensures has(key); @ ensures valueFor(key)==value; @ ensures count()==(\old(count())+1); @*/ public void put(Object key, Object value); Hvad hvis vi tillader, at key er der i forvejen? Dvs. svækker prebetingelsen? Denne del af postbetingelsen holder i så fald ikke længere!

13 FEN 2013-05-19KbP/seminar3: subcontracts13 Guarded postconditions /*@ requires !has(key); @ ensures has(key); @ ensures (!\old(has(key))) ==> (valueFor(key)==value); @ ensures (!\old(has(key))) ==> (count()==(\old(count())+1)); @*/ public void put(Object key, Object value); •Guarded postcondition ændrer ikke klassens specifikation. Det er kun forberedelse på omdefinering i en subklasse. Jf. keyword virtual i C#, som kun muliggør override i en evt. kommende subklasse. Post-betingelsen er bevogtet (guarded) af den tilsvarende prebetingelse Dictionary2

14 FEN 2013-05-19KbP/seminar3: subcontracts14 Designregel •For at understøtte redefinering af metoder i subklasser bør alle postbetingelser beskyttes af deres tilsvarende prebetingelse •Ex: void pip() //PREq //POSTr -- bør være q  r

15 FEN 2013-05-19KbP/seminar3: subcontracts15 Guarded postcondition muliggør fx: class A { public void pip(){}; //PRE p //POST p  q }; class B extends A { public void pip(){}; //PRE p’ //POST p  q //POST p’  q’ }; Prebetingelsen kan afsvækkes Hvis den gamle prebetingelse er opfyldt, så holder den gamle postbetingelse også Ny postbetingelse svarende til den nye prebetingelse kan tilføjes

16 FEN 2013-05-19KbP/seminar3: subcontracts16 Dictionary2: public interface Dictionary2 { /*@ invariant count()>=0; @*/ // Basic queries public /*@ pure @*/ int count(); /*@ ensures (count()==0) ==> (!\result); @*/ public /*@ pure @*/ boolean has(Object key); /*@ requires has(key); @*/ public /*@ pure @*/ Object valueFor(Object key); // Derived queries /*@ ensures \result == (count()==0); @*/ public boolean isEmpty(); /*@ requires !has(key); @ ensures has(key); @ ensures (!\old(has(key))) ==> (valueFor(key)==value); @ ensures (!\old(has(key))) ==> (count()==(\old(count())+1)); @*/ public void put(Object key, Object value); /*@ requires has(key); @ ensures !has(key); @ ensures (\old(has(key))) ==> (count()==(\old(count())-1)); @*/ public void remove(Object key); Post-betingelserne er bevogtet (guarded) af den tilsvarende prebetingelse

17 FEN 2013-05-19KbP/seminar3: subcontracts17 Redefinering af Dictionary2 •Vi vil gerne lave et nyt dictionary (RelaxedDictionary2), hvor det bl.a. er muligt: –at kalde put med en key, som allerede er i dictionary’et. I så fald skal put gøre ingenting –at kalde remove med en key, som ikke er dictionary’et. I så fald gør remove ingenting

18 FEN 2013-05-19KbP/seminar3: subcontracts18 Subklassen public interface RelaxedDictionary2 extends Dictionary2 { /*@ also @ requires has(key); @ ensures \old(has(key)) ==> @ valueFor(key)==\old(valueFor(key)); @ ensures \old(has(key)) ==> count()==\old(count()); @*/ public void put(Object key, Object value); Den arvede prebetingelse OR’es på: !has(key) OR has(key)  true Den arvede post-betingelse AND’es på: !\old(has(key)) ==> valueFor(key)==value AND \old(has(key)) ==> valueFor(key)==\old(valueFor(key)) Nødvendig i JML, når en arving udvider en spec /*@ also @ requires !has(key); @ ensures !\old(has(key)) ==> count()==\old(count()); @*/ public void remove(Object key); }

19 FEN 2013-05-19KbP/seminar3: subcontracts19 Øvelse •Definér kontrakten på Queue med guarded postconditions •Skriv et interface RelaxedQueue med kontrakt, som extend'er Queue og omdefinerer head(), så: 1.det er lovligt at forsøge at udtage et element fra en tom kø, 2.resultatet bliver null, og 3.køen ikke ændres herved. RelaxedQueue

20 FEN 2013-05-19KbP/seminar3: subcontracts20 Specifikation af Queue public interface Queue { /*@ invariant size()>=0; @*/ // Basic queries public /*@ pure @*/ int size(); /*@ requires 0<=i && i<size(); @*/ public /*@ pure @*/ Object get(int i); // Derived queries /*@ requires size()>0; @ ensures \result == get(0); @*/ public /*@ pure @*/ Object head(); /*@ ensures \result == (size()==0); @*/ public /*@ pure @*/ boolean isEmpty(); /*@ ensures \result.size()==size(); @ ensures (\forall int i; 0<=i && i<=size()-1; @ (\result.get(i)==get(i))); @*/ public Queue shallowCopy(); // Commands /*@ ensures size()==\old(size())+1; @ ensures get(size()-1)==o; @*/ public void put(Object o); /*@ requires size()>=1; @ ensures size()==\old(size())-1; @ ensures (\forall int i; 0<=i && i<=size()-2; @ \old(shallowCopy()).get(i+1) == get(i)); @*/ public void remove(); }

21 Code Contracts •I Code Contracts er det ike muligt at ændre pre-betingelser (endnu). •Argumentet er, at det ikke er nyttigt (sic!) •Men så undgår man problemer med type co-varians  FEN 2013-05-19KbP/seminar3: subcontracts21


Download ppt "FEN 2013-05-19KbP/seminar3: subcontracts1 Kontraktbaseret programmering Seminar 3 Kontrakter og arv Underleverandørsyn Substitutionsprincippet Guarded."

Lignende præsentationer


Annoncer fra Google