Chair of Software Engineering OOSC Summer Semester Object-Oriented Software Construction Bertrand Meyer
Chair of Software Engineering OOSC Summer Semester Lecture 7: Inheritance by Piotr Nienaltowski
Chair of Software Engineering OOSC Summer Semester What do you want to learn today? What is inheritance? Redefinition of features Polymorphism and dynamic binding Inheritance and Design by Contract Inheritance vs. genericity Assignment attempt
Chair of Software Engineering OOSC Summer Semester What is inheritance? Principle: Describe a new class not from scratch but as extension or specialization of one existing class — or several in the case of MULTIPLE inheritance. From the module viewpoint: if B inherits from A, all the services of A are potentially available in B (possibly with a different implementation). From the type viewpoint: inheritance is the ‘‘is- plus-but-except’’ relation. If B inherits from A, whenever an instance of A is required, an instance of B will be acceptable.
Chair of Software Engineering OOSC Summer Semester Terminology Parent, Heir Ancestor, Descendant The ancestors of B are B itself and the ancestors of its parents. Proper ancestor, Proper descendant Direct instance, Instance The instances of A are the direct instances of its descendants. (Other terminology: subclass, superclass, base class) A B feature
Chair of Software Engineering OOSC Summer Semester Example hierarchy FIGURE * OPEN_ FIGURE * CLOSED_ FIGURE * SEGMENTPOLYLINEPOLYGONELLIPSE CIRCLE RECTANGLETRIANGLE SQUARE extent* barycenter* … display* rotate … perimeter* perimeter+ perimeter++ diagonal... perimeter++ ++ side1 side2 * deferred + effective ++ redefined
Chair of Software Engineering OOSC Summer Semester Redefinition class POLYGON create make feature vertices: ARRAY [POINT] vertices_count: INTEGER perimeter: REAL is -- Perimeter length do from... until... loop Result := Result + i). distance (i + 1))...end invariant vertices_count >= 3 vertices_count = vertices.count end i (i + 1)
Chair of Software Engineering OOSC Summer Semester class RECTANGLE inherit POLYGON redefine perimeter end create make feature diagonal, side1, side2: REAL perimeter: REAL is -- Perimeter length do Result := 2 * (side1 + side2) end invariant vertices_count = 4 end Redefinition (cont’d) side1 side2
Chair of Software Engineering OOSC Summer Semester Assume: p: POLYGON; r: RECTANGLE; t: TRIANGLE; x: REAL Permitted: x := p.perimeter x := r.perimeter x := r.diagonal p := r NOT permitted: x := p.diagonal (even just after p := r !) r := p Inheritance, typing and polymorphism (POLYGON) (RECTANGLE) p r
Chair of Software Engineering OOSC Summer Semester Dynamic binding What is the effect of the following (assuming some_test true)? if some_test then p := r else p := t end x := p.perimeter Redefinition: A class may change an inherited feature, as with RECTANGLE redefining perimeter. Polymorphism: p may have different forms at run-time. Dynamic binding: Effect of p.perimeter depends on run-time form of p.
Chair of Software Engineering OOSC Summer Semester The meaning of inheritance The type perspective: Automatic adaptation of operations to the dynamic form of their targets (extendibility): Representation independence. Factoring out reusable operations: Commonality. The module perspective (reusability): Open-closed modules Modularity The Single Choice Principle
Chair of Software Engineering OOSC Summer Semester The traditional architecture display (f: FIGURE) is do if ‘‘f is a CIRCLE’’ then... elseif ‘‘f is a POLYGON’’ then... end and similarly for all other routines!
Chair of Software Engineering OOSC Summer Semester Applying the Single Choice Principle f: FIGURE c: CIRCLE p: POLYGON... create c.make (...) create p.make (...)... if... then f := c else f := p end... f.move (...) f.rotate (...) f.display (...)...
Chair of Software Engineering OOSC Summer Semester The Open-Closed Principle ACE D B FA’ G H I
Chair of Software Engineering OOSC Summer Semester The dangers of static binding For every creation procedure cp: {pre cp } do cp {post cp and INV} For every exported routine r: {INV and pre r } do r {INV and post r } The worst possible erroneous run-time situation in object-oriented software development: Producing an object that does not satisfy the invariant of its class. a.f (…) a.g (…) a.f (…) create a.make (…) S1 S2 S3 S4
Chair of Software Engineering OOSC Summer Semester The dangers of static binding (cont’d) {INV A } do r A {INV A } {INV B } do r B {INV B } Consider a call of the form a1.r where a1 is polymorphic: No guarantee on the effect of do r A on an instance of B! A B rArA r B ++
Chair of Software Engineering OOSC Summer Semester A concrete example w: WINDOW b: BUTTON create b w := b w.display WINDOW BUTTON display display++
Chair of Software Engineering OOSC Summer Semester Using original version of redefined feature class BUTTON inherit WINDOW redefine display end feature display is do Precursor display_border display_label end display_label is do... end display_border is do... end
Chair of Software Engineering OOSC Summer Semester Use of Precursor Not necessarily the first feature statement. May have arguments. class B inherit A redefine my_feature end feature my_feature (args: SOME_TYPE) is do -- Something here Precursor (args) -- Something else here end A B my_feature my_feature++
Chair of Software Engineering OOSC Summer Semester Inheritance and assertions Correct call: if a1. then a1.r (...) else... end r is require ensure r is require ensure CA B a1: A a1.r (…) …
Chair of Software Engineering OOSC Summer Semester Redefined version may not have require or ensure. May have nothing (assertions kept by default), or require else new_pre ensure then new_post Resulting assertions are: original_precondition or new_pre original_postcondition and new_post Assertion redeclaration rule
Chair of Software Engineering OOSC Summer Semester Invariant accumulation Every class inherits all the invariant clauses of its parents. These clauses are conceptually “and”-ed.
Chair of Software Engineering OOSC Summer Semester Genericity vs. Inheritance LIST_OF_ BOOKS SET_OF_ BOOKS LINKED_LIST _OF_BOOKS LIST_OF_ PEOPLE LIST_OF_ JOURNALS Abstraction Specialization Type parameterization
Chair of Software Engineering OOSC Summer Semester Genericity + Inheritance 1: Polymorphic data structures class STACK [G] feature... item: G is... put (x: G) is... end fs: STACK [FIGURE] r: RECTANGLE s: SQUARE t: TRIANGLE p: POLYGON... fs.put (p); fs.put (t); fs.put (s); fs.put (r) fs.item.display (SQUARE) (RECTANGLE) (TRIANGLE) (POLYGON) fs
Chair of Software Engineering OOSC Summer Semester Example hierarchy FIGURE * OPEN_ FIGURE * CLOSED_ FIGURE * SEGMENTPOLYLINEPOLYGONELLIPSE CIRCLE RECTANGLETRIANGLE SQUARE extent* barycenter* … display* rotate … perimeter* perimeter+ perimeter++ diagonal... perimeter++ ++ side1 side2 * deferred + effective ++ redefined
Chair of Software Engineering OOSC Summer Semester Genericity + Inheritance 2: Constrained genericity class VECTOR [G -> NUMERIC] feature infix "+" (other: VECTOR [G]): VECTOR [G] is -- Sum of current vector and other require lower = other.lower upper = other.upper local a, b, c: G do... See next... end... Other features... end
Chair of Software Engineering OOSC Summer Semester Constrained genericity (cont’d) The body of infix "+": create Result.make (lower, upper) from i := lower until i > upper loop a := item (i) b := other.item (i) c := a + b-- Requires a “+” operation on G! Result.put (c, i) i := i + 1 end
Chair of Software Engineering OOSC Summer Semester Constrained genericity (cont’d) The body of infix "+": create Result.make (lower, upper) from i := lower until i > upper loop a := item (i) b := other.item (i) c := a + b-- Requires a “+” operation on G! Result.put (c, i) i := i + 1 end
Chair of Software Engineering OOSC Summer Semester The solution Declare class VECTOR as class VECTOR [G –> NUMERIC] feature... The rest as before... end Class NUMERIC (from the Kernel Library) provides features infix "+", infix "*" and so on.
Chair of Software Engineering OOSC Summer Semester Improving the solution Make VECTOR itself a descendant of NUMERIC, effecting the corresponding features: class VECTOR [G –> NUMERIC] inherit NUMERIC feature... The rest as before, including infix "+"... end Then it is possible to define e.g. v: VECTOR [VECTOR [VECTOR [INTEGER]]]
Chair of Software Engineering OOSC Summer Semester Forcing a type: the problem fs.store ("FILE_NAME") Two years later: fs.retrieve ("FILE_NAME") x := fs.item-- [1] print (x.diagonal)-- [2] But: If x is declared of type RECTANGLE, [1] is invalid. If x is declared of type FIGURE, [2] is invalid.
Chair of Software Engineering OOSC Summer Semester Assignment attempt f: FIGURE r: RECTANGLE... fs.retrieve ("FILE_NAME") f := fs.item r ?= f if r /= Void then print (r.diagonal) else print ("Too bad.") end
Chair of Software Engineering OOSC Summer Semester Assignment attempt (cont’d) x ?= y with x: A If y is attached to an object whose type conforms to A, perform normal reference assignment. Otherwise, make x void.
Chair of Software Engineering OOSC Summer Semester End of lecture 7