Chair of Software Engineering ATOT - Lecture 8, 28 April Advanced Topics in Object Technology Bertrand Meyer
Chair of Software Engineering ATOT - Lecture 8, 28 April Lecture 8: Inheritance
Chair of Software Engineering ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April Redefinition (cont’d) 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 side1 side2
Chair of Software Engineering ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 POLYGON 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April The Open-Closed Principle ACE D B FA’ G H I
Chair of Software Engineering ATOT - Lecture 8, 28 April Issues Representation independance: Can a client request an operation such as table search (has) without knowing what implementation is used internally? has (t1, y) Now: t1.has (y)
Chair of Software Engineering ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April A concrete example w: WINDOW b: BUTTON create b w := b w.display WINDOW BUTTON display display++
Chair of Software Engineering ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April Genericity vs. Inheritance LIST_OF_ BOOKS SET_OF_ BOOKS LIKED_LIST_ OF_BOOKS LIST_OF_ PEOPLE LIST_OF_ JOURNALS Abstraction Specialization Type parameterization
Chair of Software Engineering ATOT - Lecture 8, 28 April Forcing a type: the problem fs.store ("FILE_NAME") Two years later: fs := retrieved ("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 ATOT - Lecture 8, 28 April The solution: Assignment attempt fs.store ("FILE_NAME") Two years later: fs ?= retrieved ("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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April Genericity + Inheritance 2: Constrained genericity class VECTOR [G] 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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. Better yet: make VECTOR itself a descendant of NUMERIC, effecting the corresponding features:
Chair of Software Engineering ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April 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 ATOT - Lecture 8, 28 April Invariant accumulation Every class inherits all the invariant clauses of its parents. These clauses are conceptually “and”-ed.
Chair of Software Engineering ATOT - Lecture 8, 28 April End of lecture 8