Liskov 7

advertisement
Type Abstraction
Liskov, Chapter 7
Liskov Substitution Principle
In any client code, if the supertype
object is substituted by a subtype
object, the client’s expectations will still
be satisfied.
Everyone learns this in intro OO courses,
but this is a lot harder than it looks.
2
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!
3
Extended behavior

Extended Behavior



Specialize the behavior of supertype
Classic ‘IS A’ relationship
Usually has additional rep.
Bike
Car
Vehicle
Constraint View: for contracts
CAR
Vehicle
Object View: for rep
4
Conflict in two goals?
Poly
SparsePoly
Poly
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
5
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
Which toString() method is called? Object.toString(),
String.toString() or Integer.toString()?
At run time, “best fit” code is called.
6
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; }
7
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
8
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.
9
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;
}
10
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()????
11
Meaning of subtypes


Subtypes behavior must support
supertype behavior – (SP)
In particular following three
properties:
1.
2.
3.
Signature Rule
Methods Rule
Properties Rule
12
Signature Rule


Subtypes must have all methods of supertype
Signatures of methods must be compatible
with supertype signature



Return types identical; Covariant after Java 1.5
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
13
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?
14
Methods Rule
1.
Cannot take away methods!
1.
2.
Subtype API should atleast be equal or
greater than supertype API
Must maintain the contract!
1.
2.
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?
15
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
16
Post condition rule


Informally, 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?
17
Same Diagram as Method
Verification
Supertype State (Pre-Super)
Supertype State (Post-Super)
SuperType Method
Contract
?
AF()
AF()
Subtype State (Pre-Sub)
Subtype
Subtype State (Post-Sub)
Method
Contract
18
Examples

Super
Satisfies Signature

and Method rules
Sub
public void addZero()
//pre: this is not empty
//post: add zero to this
public void addZero()
//post: add zero to this
public void addZero()
throws ISE
//pre: this is not empty
//post: add zero to this
public void addZero()
throws ISE
//post: if this is empty,
throw ISE else add zero
to this
Satisfies Signature
and Method rules
19
More examples

Super
Does not satisfy
Signature rule
public void addZero()
//pre: this is not empty
//post: add zero to this
public void addZero() throws
ISE
//post: if this is empty,
throws ISE
// else add zero to this

Sub
public void addZero() throws
ISE
//post: add zero to this
public void addZero()
//post: add zero to this
Does not satisfy Postcondition
part of methods rule
20
A Java Example

What may subtypes of Iterator do?
21
Client code
private void foo {
…
try{
o.addZero();
} (catch EE){
//do something: Client expects to get here!
}
}
22
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).
23
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
}
24
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?
25
More About Properties Rule
Collection <String> c = ...;
c.add
(“cat”);
c.add
(“cat”);
c.remove(“cat”);
//
//
//
if
consider the following observer call:
What is behavior if c is a Set?
What is behavior if c is a Bag?
(c.contains(“cat”) { ... }
// Such “algebraic” relations are extremely useful for testing
26
Download