270 likes | 371 Vues
Type Abstraction. SWE 619 - Spring 2009. Substitution Principle. “In any client code, if supertype object is substituted by subtype object, the client will not notice any difference in behavior” Object o = getNewObject(); Case 1: public Object getNewObject();
E N D
Type Abstraction SWE 619 - Spring 2009
Substitution Principle “In any client code, if supertype object is substituted by subtype object, the client will not notice any difference in behavior” • Object o = getNewObject(); • Case 1: public Object getNewObject(); • Case 2: public String getNewObject();
Why do we subtype? • Extended Behavior • Standard “Is-A” Relationships • Multiple implementations • SparsePoly, DensePoly • Different implementations • Same specifications • All supertype behavior must be supported • No extra stuff!
Vehicle Car Bike Extended behavior • Extended Behavior • Specialize the behavior of supertype • Classic ‘IS A’ relationship • Usually has additional rep. CAR Vehicle Constraint View: for contracts Object View: for rep
Conflict in two goals? Poly Poly SparsePoly DensePoly LogPoly SparsePoly DensePoly LogPoly: Extends the behavior of Poly by keeping track of how many times it was accessed by the calling code. It has additional rep (a log of accesses) LogPoly
Dispatching Object[] x = new Object[2]; X[0] = new String(“abc”); X[1] = new Integer(1); for(int i=0; i<x.length;i++) System.out.println(x[i].toString()); • Compiler does not complain (apparent type is fine!) • Which toString method is called? Object.toString(), String.toString() or Integer.toString()? • At run time, “best fit” code is called.
MaxIntSet Example (Fig 7.5) public class MaxIntSet extends IntSet { private int biggest; // biggest element of set if not empty public MaxIntSet {super (); } //Why call super() ??? public void insert (int x) { if (size() == 0 || x > biggest) biggest = x; super.insert(x); } public int max () throws EmptyException { if (size() == 0) throw new EmptyException (“MaxIS.max”); return biggest; }
MaxIntSet.remove() public void remove (int x) { super.remove(x); if (size()==0 || x <biggest) return; Iterator g = elements(); biggest = ((Integer) g.next()).intValue(); while (g.hasNext() { int z = ((Integer) g.next()).intValue(); if (z>biggest) biggest = z; } • Need to call supertype’s remove functionality. (private rep!) • Must maintain subtype’s rep invariant
MaxIntSet.repOk() public boolean repOk() { if (!super.repOk()) return false; if (size() == 0) return true; boolean found = false; Iterator g = elements(); while(g.hasNext()) { int z = ((Integer)g.next()).intValue(); if (z>biggest) return false; if (z==biggest) found = true; return found; }
MaxIntSet Abstract State // Overview: MaxIntSet is a subtype of IntSet with an additional // method, max, to determine the maximum element of the set • Two possible abstract states: • {x1, x2, ... xN} - same as IntSet • <biggest, {x1, x2, ... xN}> - visible abstract state • Which one to choose? • Design decision - either is possible • Second may seem more natural, but there are significant advantages to the first. • We will revisit this via Bloch later in the semester.
repOk() and Dynamic Dispatching public class IntSet { public void insert(int x) {...; repOk();} public void remove(int x) {...; repOk();} // where to? public boolean repOk() {...} } public class MaxIntSet extends IntSet { public void insert(int x) {...; super.insert(x); repOk();} public void remove(int x) {super.remove(x); ...; repOk(); public boolean repOk() {super.repOk(); ...;} } MaxIntSet s = {3, 5}; s.remove(5); // repOk()????
Mechanisms: Abstract class • Defines a type + partial implementation • Contains both abstract methods and concrete methods • May have instance variables + constructor • Users can’t call constructor • Subtype extends the supertype • Can call constructors to initialize supertype rep. • Template pattern
Mechanisms: Interface • Defines a type (no implementation) • Only non static public method • All methods are abstract • Implementation is provided by a class that implements the interface public class foo implements someInterface { … }
Meaning of subtypes • Subtypes behavior must support supertype behavior – (SP) • In particular following three properties: • Signature Rule • Methods Rule • Properties Rule
Signature Rule • Subtypes must have all methods of supertype • Signatures of methods must be compatible with supertype signature • Return types must be same • Guaranteed by Java compiler • Caution: Overriding vs. overloading public boolean equals(Foo foo) {...} public boolean equals(Object foo) {...} • Exceptions • Signature Rule allows Subtype to throw fewer • But methods rule must be satisfied
Methods Rule • When object belongs to subtype, subtype method is called • We must still be able to reason about these methods using supertype specs Suppose SortedIntSet extends IntSet IntSet x = new IntSet(); IntSet y = new SortedIntSet(); x.insert(3); //What is this_post? y.insert(3); //What is this_post?
Methods Rule • Cannot take away methods! • Subtype API should atleast be equal or greater than supertype API • Must maintain the contract! • Precondition rule: What can a subclass do with preconditions in supertype spec? • Post condition rule: What can a subclass do with postconditions in supertype spec?
Precondition rule • Subtype is allowed to weaken the precondition! • Formally: • pre_super |- pre_sub • Super //Requires: x > 5 • Case 1: Sub //Requires x > 6 • Case 2: Sub // Requires x > 4 • x>5 x>4? Which is weaker? • x>5 x>6? • Not checked by compiler
Post condition rule • Subtype is allowed to strengthen the post condition • Formally: • pre_super && post_sub |- post_super • Super: // Effects: returns y < 5 • Sub: //Effects: returns y < 4 • Sub: //Effects: returns y < 6 • Which one is a stronger condition?
Same Diagram as Method Verification Supertype State (Pre-Super) Supertype State (Post-Super) SuperType Method Contract ? AF() AF() Subtype State (Post-Sub) Subtype State (Pre-Sub) Subtype Method Contract
Super public void addZero() //R: this is not empty //E: add zero to this public void addZero() throws EE //R: this is not empty //E: add zero to this Sub public void addZero() //E: add zero to this public void addZero() throws EE //R: true //E: if this is empty, throw EE else add zero to this Other examples
Super public void addZero() //R: this is not empty //E: add zero to this public void addZero() throws EE //E: if this is empty, throws EE // else add zero to this Sub public void addZero() throws EE //E: add zero to this public void addZero() //R: true //E: add zero to this More examples
Client code private void foo { … try{ o.addZero(); } (catch EE){ //do something: Client expects to get here! } }
Methods rule vs. Properties rule • Methods rule is for single method invocation • Properties rule about abstract objects. • Invariants: E.g. IntSets do not contain duplicates • s.isIn(x) following s.remove(x) always false • Evolution properties: E.g. MonotoneSets only grow (no remove method allowed).
Liskov 7.8, 7.9, 7.10 public class Counter{ // Liskov 7.8 public Counter() //EFF: Makes this contain 0 public int get() //EFF: Returns the value of this public void incr() //MOD: this //EFF: Increments value of this } public class Counter2 extends Counter { // Liskov 7.9 public Counter2() //EFF: Makes this contain 0 public void incr() // MOD: this //EFF: double this } public class Counter3 extends Counter { // Liskov 7.10 public Counter3(int n) //EFF: Makes this contain n public void incr(int n) // MOD: this //EFF: if n>0 add n to this }
Anaylsis • Signature rule: Careful with over- load vs. ride • Counter2 ok? • Counter3 ok? • Methods rule: • Precondition rule: • Counter 2 ok? • Counter 3 ok? • Postcondition rule: • Counter 2 ok? • Counter 3 ok?
Liskov 7.11 • Is IntBag a legitimate subtype of IntSet? • Analysis: public void insert(int x); // Effects: ??? public void remove(int x); // Effects: ???