class rectangle double h, w rectangle(h, w) : h(h), w(w) { } virtual set_ht(h) { h = h } virtual set_wd(w) { w = w } double get_height() { return h } double get_wd() { return w } double area() { return h*w }
h == w
.
class square : rectangle square(s) : h(s), w(s) { } set_ht(ht) h = w = ht set_wd(wd) h = w = wd
void test(rectangle r) r.set_wd(4) r.set_ht(5) assert 4 == r.get_wd() ∧ 5 == r.get_ht() assert 20 == r.area() r.set_wd(4) r.set_ht(3) assert 4 == r.get_wd() ∧ 3 == r.get_ht() assert 12 == r.area()
int main() test(new rectangle(1, 1)) // pass. test(new square(1)) // fail.
A class C is a child of class P if and only if a C instance can replace any P instance without semantic change.
test()
.
// Inv: // h and w are independent ∧ // area == h*w ∧ // whatever...
rectangle::set_width()
is
set_width(wd) // Inv ∧ w == W ∧ h == H w = wd // Inv ∧ w == wd ∧ h == H
// Inv: // h == w ∧ // area == h*w ∧ // whatever...
square::set_width()
is
set_width(wd) // Inv ∧ w == W w = h = wd // Inv ∧ w == wd