4-Reusable in Design (Delegation - Inheritance and Behavioral Subtyping) Part I - 2016-12-01
4-Reusable in Design (Delegation - Inheritance and Behavioral Subtyping) Part I - 2016-12-01
Contents
1
2/8/2017
Contents
2
2/8/2017
interface Comparator {
boolean compare(int i, int j);
}
final Comparator ASCENDING = (i, j) -> i < j;
Version B final Comparator DESCENDING = (i, j) -> i > j;
static void sort(int[] list, Comparator cmp) {
…
boolean mustSwap =
cmp.compare(list[i], list[j]);
…
}
Delegation
3
2/8/2017
Delegation
4
2/8/2017
5
2/8/2017
Contents
6
2/8/2017
• Subtype polymorphism
– Different kinds of objects can be processed
uniformly by client code
– Each object behaves according to its type
• e.g., if you add new kind of account, client code does
not change:
If today is the last day of the month:
For each acct in allAccounts:
acct.monthlyAdjustment();
7
2/8/2017
8
2/8/2017
Benefits of inheritance
• Reuse of code
• Modeling flexibility
• Note in Java:
– Each class can directly extend only one parent
class
– A class can implement multiple interfaces
9
2/8/2017
10
2/8/2017
11
2/8/2017
12
2/8/2017
Note: instanceof
13
2/8/2017
Contents
14
2/8/2017
Behavioral subtyping
Homework
15
2/8/2017
Behavioral subtyping
(Liskov Substitution Principle)
abstract class Vehicle { class Car extends Vehicle {
int speed, limit; int fuel;
boolean engineOn;
//@ invariant speed < limit; //@ invariant speed < limit;
//@ invariant fuel >= 0;
void accelerate() { … }
Behavioral subtyping
(Liskov Substitution Principle)
class Hybrid extends Car {
class Car extends Vehicle { int charge;
int fuel; //@ invariant charge >= 0;
boolean engineOn;
//@ invariant fuel >= 0; //@ requires (charge > 0 || fuel > 0) &&
!engineOn;
//@ requires fuel > 0 && !engineOn; //@ ensures engineOn;
//@ ensures engineOn; void start() { … }
void start() { … }
void accelerate() { … }
void accelerate() { … }
//@ requires speed != 0;
//@ requires speed != 0; //@ ensures speed < \old(speed)
//@ ensures speed < old(speed) //@ ensures charge > \old(charge)
void brake() { … } void brake() { … }
} }
Subclass fulfills the same invariants (and additional ones)
Overridden method start has weaker precondition
Overridden method brake has stronger postcondition
16
2/8/2017
Behavioral subtyping
(Liskov Substitution Principle)
Behavioral subtyping
(Liskov Substitution Principle)
17
2/8/2017
Behavioral subtyping
(Liskov Substitution Principle)
Behavioral subtyping
(Liskov Substitution Principle)
18
2/8/2017
Behavioral subtyping
(Liskov Substitution Principle)
class Rectangle { class Square extends Rectangle {
//@ invariant h>0 && w>0; //@ invariant h>0 && w>0;
int h, w; //@ invariant h==w;
Rectangle(int h, int w) { Square(int w) {
this.h=h; this.w=w; super(w, w);
} }
//@ requires factor > 0; }
void scale(int factor) {
w=w*factor;
h=h*factor;
}
}
Is this Square a behavioral subtype of Rectangle?
Behavioral subtyping
(Liskov Substitution Principle)
class Rectangle { class Square extends Rectangle {
//@ invariant h>0 && w>0; //@ invariant h>0 && w>0;
int h, w; //@ invariant h==w;
Rectangle(int h, int w) { Square(int w) {
this.h=h; this.w=w; super(w, w);
} }
//@ requires factor > 0; }
void scale(int factor) {
w=w*factor;
h=h*factor;
}
}
Is this Square a behavioral subtype of Rectangle? Yes
19
2/8/2017
Behavioral subtyping
(Liskov Substitution Principle)
class Rectangle { class Square extends Rectangle {
//@ invariant h>0 && w>0; //@ invariant h>0 && w>0;
int h, w; //@ invariant h==w;
Rectangle(int h, int w) { Square(int w) {
this.h=h; this.w=w; super(w, w);
} }
//@ requires factor > 0; }
void scale(int factor) {
w=w*factor;
h=h*factor;
}
//@ requires neww > 0;
void setWidth(int neww) {
w=neww;
}
} Is this Square a behavioral subtype of Rectangle?
Behavioral subtyping
(Liskov Substitution Principle)
class Rectangle { class Square extends Rectangle {
//@ invariant h>0 && w>0; //@ invariant h>0 && w>0;
int h, w; //@ invariant h==w;
Rectangle(int h, int w) { Square(int w) {
this.h=h; this.w=w; super(w, w);
} }
//@ requires factor > 0; }
void scale(int factor) { class GraphicProgram {
w=w*factor; void scaleW(Rectangle r, int factor) {
h=h*factor; r.setWidth(r.getWidth() * factor);
} }
//@ requires neww > 0; }
void setWidth(int neww) { ← Invalidates stronger
w=neww; invariant (w==h) in subclass
}
} Is this Square a behavioral subtype of Rectangle?
Yes? (But the Square is not actually a square…)
20
2/8/2017
21