464 INTRODUCTION TO INHERITANCE $14.1 Basic conventions and terminology The following terms will be useful in addition to"heir'”and“parent'”. Inheritance terminology A descendant ofa class C is any class that inherits directly or indirectly from C,including C itself.(Formally:either C or,recursively,a descendant of an heir of C.) A proper descendant of C is a descendant other than C itself. An ancestor of C is a class 4 such that C is a descendant of 4.A proper ancestor of C is a class 4 such that C is a proper descendant of A. In the literature you will also encounter the terms“subclass”and“superclass”,but we will stay away from them because they are ambiguous;sometimes"subclass"means heir (immediate descendant),sometimes it is used in the more general sense of proper descendant,and it is not always clear which.In addition,we will see that the "subset" connotation of this word is not always justified. Associated terminology applies to the features of a class:a feature is either inherited (coming from a proper ancestors)or immediate (introduced in the class itself). In graphical representations of object-oriented software structures,where classes are represented by ellipses("bubbles"),inheritance links will appear as single arrows.This distinguishes them from links for the other basic inter-class relation,client,which as you will recall uses a double arrow.(For further distinction this book uses black for client and color for inheritance. perimeter POLYGON An inheritance link diagonal Inherits from perimeter+ RECTANGLE A redefined feature is marked,a convention from the Business Object Notation (B.O.N.). The arrow points upward,from the heir to the parent;the convention,easy to remember,is that it represents the relation "inherits from".In some of the literature you will find the reverse practice;although in general such choices of graphical convention are partly a matter of taste,in this case one convention appears definitely better than the other in the sense that one suggests the proper relationship and the other may lead to confusion.An arrow is not just an arbitrary pictogram but indicates a unidirectional link, between the two ends of the arrow.Here:
464 INTRODUCTION TO INHERITANCE §14.1 Basic conventions and terminology The following terms will be useful in addition to “heir” and “parent”. In the literature you will also encounter the terms “subclass” and “superclass”, but we will stay away from them because they are ambiguous; sometimes “subclass” means heir (immediate descendant), sometimes it is used in the more general sense of proper descendant, and it is not always clear which. In addition, we will see that the “subset” connotation of this word is not always justified. Associated terminology applies to the features of a class: a feature is either inherited (coming from a proper ancestors) or immediate (introduced in the class itself). In graphical representations of object-oriented software structures, where classes are represented by ellipses (“bubbles”), inheritance links will appear as single arrows. This distinguishes them from links for the other basic inter-class relation, client, which as you will recall uses a double arrow. (For further distinction this book uses black for client and color for inheritance.) A redefined feature is marked ++, a convention from the Business Object Notation (B.O.N.). The arrow points upward, from the heir to the parent; the convention, easy to remember, is that it represents the relation “inherits from”. In some of the literature you will find the reverse practice; although in general such choices of graphical convention are partly a matter of taste, in this case one convention appears definitely better than the other — in the sense that one suggests the proper relationship and the other may lead to confusion. An arrow is not just an arbitrary pictogram but indicates a unidirectional link, between the two ends of the arrow. Here: Inheritance terminology A descendant of a class C is any class that inherits directly or indirectly from C, including C itself. (Formally: either C or, recursively, a descendant of an heir of C.) A proper descendant of C is a descendant other than C itself. An ancestor of C is a class A such that C is a descendant of A. A proper ancestor of C is a class A such that C is a proper descendant of A. An inheritance link POLYGON RECTANGLE perimeter diagonal perimeter++ Inherits from
$14.1 POLYGONS AND RECTANGLES 465 Any instance ofthe heir may be viewed (as we shall see in more detail)as an instance of the parent,but not conversely. The text of the heir will always mention the parent(as in the inherit clause above), but not conversely;it is in fact an important property of the method,resulting among others from the Open-Closed principle,that a class does not"know"the list of its heirs and other proper descendants. Mathematically,the direction of the relationship is reflected in algebraic models for inheritance,which use a morphism (a generalization of the notion of function)from the heir's model to the parent's model-not the other way around.One more reason for drawing the arrow from the heir to the parent. Although with complex systems we cannot have an absolute rule for class placement in inheritance diagrams,we should try whenever possible to position a class above its heirs. Invariant inheritance You will have noticed the invariant of class RECTANGLE,which expresses that the number of sides is four and that the successive edge lengths are sidel,side2,side/and side2. Class POLYGON also had an invariant,which still applies to its heir: Invariant inheritance rule The invariant property ofa class is the boolean and ofthe assertions appearing in its invariant clause and of the invariant properties of its parents if any. Because the parents may themselves have parents,this rule is recursive:in the end the full invariant of a class is obtained by anding the invariant clauses of all its ancestors. The rule reflects one of the basic characteristics of inheritance:to say that B inherits from A is to state that one may view any instance of B also as an instance of4(more on this property later).As a result,any consistency constraint applying to instances of4,as expressed by the invariant,also applies to instances of B. In the example,the second clause (at least three)invariant of POLYGON stated that the number of sides must be at least three;this is subsumed by the four sides subclause in RECTANGLE's invariant clause,which requires it to be exactly four. You may wonder what would happen if the heir's clause,instead of making the parent's redundant as here (since count=4 implies count >=3),were incompatible with it,as with an heir of POLYGON that would introduce the invariant clause count=2.The result is simply an inconsistent invariant,not different from what you get if you include,in the invariant of a single class,two separate subclauses that read count>=3 and count=2. Inheritance and creation Although it was not shown,a creation procedure for POLYGON might be of the form
§14.1 POLYGONS AND RECTANGLES 465 • Any instance of the heir may be viewed (as we shall see in more detail) as an instance of the parent, but not conversely. • The text of the heir will always mention the parent (as in the inherit clause above), but not conversely; it is in fact an important property of the method, resulting among others from the Open-Closed principle, that a class does not “know” the list of its heirs and other proper descendants. Mathematically, the direction of the relationship is reflected in algebraic models for inheritance, which use a morphism (a generalization of the notion of function) from the heir’s model to the parent’s model — not the other way around. One more reason for drawing the arrow from the heir to the parent. Although with complex systems we cannot have an absolute rule for class placement in inheritance diagrams, we should try whenever possible to position a class above its heirs. Invariant inheritance You will have noticed the invariant of class RECTANGLE, which expresses that the number of sides is four and that the successive edge lengths are side1, side2, side1 and side2. Class POLYGON also had an invariant, which still applies to its heir: Because the parents may themselves have parents, this rule is recursive: in the end the full invariant of a class is obtained by anding the invariant clauses of all its ancestors. The rule reflects one of the basic characteristics of inheritance: to say that B inherits from A is to state that one may view any instance of B also as an instance of A (more on this property later). As a result, any consistency constraint applying to instances of A, as expressed by the invariant, also applies to instances of B. In the example, the second clause (at_least_three) invariant of POLYGON stated that the number of sides must be at least three; this is subsumed by the four_sides subclause in RECTANGLE’s invariant clause, which requires it to be exactly four. You may wonder what would happen if the heir’s clause, instead of making the parent’s redundant as here (since count = 4 implies count >= 3), were incompatible with it, as with an heir of POLYGON that would introduce the invariant clause count = 2. The result is simply an inconsistent invariant, not different from what you get if you include, in the invariant of a single class, two separate subclauses that read count >= 3 and count = 2. Inheritance and creation Although it was not shown, a creation procedure for POLYGON might be of the form Invariant inheritance rule The invariant property of a class is the boolean and of the assertions appearing in its invariant clause and of the invariant properties of its parents if any
466 INTRODUCTION TO INHERITANCE $14.I make polygon (vl:LINKED LIST [POINT])is --Set up with vertices taken from vl. require vl.count>=3 do 。。 Initialize polygon representation from the items of v/... ensure --vertices and v/have the same items (can be expressed formally) end This procedure takes a list of points,containing at least three elements,and uses it to set up the polygon The procedure has been given a special name make polygon to avoid any name conflict See“FEATURE when RECTANGLE inherits it and introduces its own creation procedure make.This is RENAMING”,I5.2. not the recommended style;in the next chapter we will learn how to give the standard page 535. name make to the creation procedure in POLYGON,and use renaming in the inheritance clause of RECTANGLE to remove any name clash. The creation procedure of class RECTANGLE,shown earlier,took four arguments: a point to serve as center,the two side lengths and an orientation.Note that feature vertices is still applicable to rectangles;as a consequence,the creation procedure of RECTANGLE should set up the vertices list with the appropriate point values (the four corners,to be computed from the center,side lengths and orientation given as arguments). The creation procedure for general polygons is awkward for rectangles,since only lists of four elements satisfying the invariant of class RECTANGLE would be acceptable Conversely,the creation procedure for rectangles is not appropriate for arbitrary polygons. This is a common case:a parent's creation procedure is not necessarily right as creation procedure for the heir.The precise reason is easy to spot;it follows from the observation that a creation procedure's formal role is to establish the class invariant.The parent's creation procedure was required to establish the parent's invariant;but,as we have seen, the heir's invariant may be stronger (and usually is);we cannot then expect that the original procedure will guarantee the new invariant. In the case of an heir adding new attributes,the creation procedures might need to initialize these attributes and so require extra arguments.Hence the general rule: Creation Inheritance rule An inherited feature's creation status in the parent class (that is to say, whether or not it is a creation procedure)has no bearing on its creation status in the heir. An inherited creation procedure is still available to the heir as a normal feature of the class (although,as we shall see,the heir may prefer to make it secret);but it does not by default retain its status as a creation procedure.Only the procedures listed in the heir's own creation clause have that status
466 INTRODUCTION TO INHERITANCE §14.1 make_polygon (vl: LINKED_LIST [POINT]) is -- Set up with vertices taken from vl. require vl ● count >= 3 do … Initialize polygon representation from the items of vl … ensure -- vertices and vl have the same items (can be expressed formally) end This procedure takes a list of points, containing at least three elements, and uses it to set up the polygon. The procedure has been given a special name make_polygon to avoid any name conflict when RECTANGLE inherits it and introduces its own creation procedure make. This is not the recommended style; in the next chapter we will learn how to give the standard name make to the creation procedure in POLYGON, and use renaming in the inheritance clause of RECTANGLE to remove any name clash. The creation procedure of class RECTANGLE, shown earlier, took four arguments: a point to serve as center, the two side lengths and an orientation. Note that feature vertices is still applicable to rectangles; as a consequence, the creation procedure of RECTANGLE should set up the vertices list with the appropriate point values (the four corners, to be computed from the center, side lengths and orientation given as arguments). The creation procedure for general polygons is awkward for rectangles, since only lists of four elements satisfying the invariant of class RECTANGLE would be acceptable. Conversely, the creation procedure for rectangles is not appropriate for arbitrary polygons. This is a common case: a parent’s creation procedure is not necessarily right as creation procedure for the heir. The precise reason is easy to spot; it follows from the observation that a creation procedure’s formal role is to establish the class invariant. The parent’s creation procedure was required to establish the parent’s invariant; but, as we have seen, the heir’s invariant may be stronger (and usually is); we cannot then expect that the original procedure will guarantee the new invariant. In the case of an heir adding new attributes, the creation procedures might need to initialize these attributes and so require extra arguments. Hence the general rule: An inherited creation procedure is still available to the heir as a normal feature of the class (although, as we shall see, the heir may prefer to make it secret); but it does not by default retain its status as a creation procedure. Only the procedures listed in the heir’s own creation clause have that status. Creation Inheritance rule An inherited feature’s creation status in the parent class (that is to say, whether or not it is a creation procedure) has no bearing on its creation status in the heir. See “FEATURE RENAMING”, 15.2, page 535
$14.2 POLYMORPHISM 467 In some cases,of course,a parent's creation procedure may still be applicable as a creation procedure;then you will simply list it in the creation clause: class B inherit A creation make feature 小小 where make is inherited-without modification-from 4,which also listed it in its own creation clause. An example hierarchy For the rest of the discussion it will be useful to consider the POLYGON-RECTANGLE example in the context of a more general inheritance hierarchy of geometrical figure types, such as the one shown on the next page Figures have been classified into open and closed variants.Along with polygons,an example of closed figure is the ellipse,a special case of the ellipse is the circle. Various features appear next to the applicable classes.The symbol+,as noted, means "redefined";the symbols and will be explained later. In the original example,for simplicity,RECTANGLE was directly an heir of POLYGON.Since the sketched classification of polygons is based on the number of vertices,it seems preferable to introduce an intermediate class OUADRANGLE,at the same level as TR/ANGLE,PENTAGON and similar classes.Feature diagonal can be moved up to the level of OUADRANGLE. Note the presence of SOUARE,an heir to RECTANGLE,characterized by the invariant side/side2.Similarly,an ellipse has two focuses (or foci),which for a circle are the same point,giving CIRCLE an invariant property of the form equal (focusl =focus2). 14.2 POLYMORPHISM Inheritance hierarchies will give us considerable flexibility for the manipulation of objects,while retaining the safety of static typing.The supporting techniques, polymorphism and dynamic binding,address some of the fundamental issues of software architecture discussed in part B of this book.Let us begin with polymorphism. Polymorphic attachment "Polymorphism"means the ability to take several forms.In object-oriented development what may take several forms is a variable entity or data structure element,which will have the ability,at run time,to become attached to objects of different types,all controlled by the static declaration
§14.2 POLYMORPHISM 467 In some cases, of course, a parent’s creation procedure may still be applicable as a creation procedure; then you will simply list it in the creation clause: class B inherit A creation make feature … where make is inherited — without modification — from A, which also listed it in its own creation clause. An example hierarchy For the rest of the discussion it will be useful to consider the POLYGON-RECTANGLE example in the context of a more general inheritance hierarchy of geometrical figure types, such as the one shown on the next page. Figures have been classified into open and closed variants. Along with polygons, an example of closed figure is the ellipse; a special case of the ellipse is the circle. Various features appear next to the applicable classes. The symbol ++, as noted, means “redefined”; the symbols + and * will be explained later. In the original example, for simplicity, RECTANGLE was directly an heir of POLYGON. Since the sketched classification of polygons is based on the number of vertices, it seems preferable to introduce an intermediate class QUADRANGLE, at the same level as TRIANGLE, PENTAGON and similar classes. Feature diagonal can be moved up to the level of QUADRANGLE. Note the presence of SQUARE, an heir to RECTANGLE, characterized by the invariant side1 = side2. Similarly, an ellipse has two focuses (or foci), which for a circle are the same point, giving CIRCLE an invariant property of the form equal (focus1 = focus2). 14.2 POLYMORPHISM Inheritance hierarchies will give us considerable flexibility for the manipulation of objects, while retaining the safety of static typing. The supporting techniques, polymorphism and dynamic binding, address some of the fundamental issues of software architecture discussed in part B of this book. Let us begin with polymorphism. Polymorphic attachment “Polymorphism” means the ability to take several forms. In object-oriented development what may take several forms is a variable entity or data structure element, which will have the ability, at run time, to become attached to objects of different types, all controlled by the static declaration
468 INTRODUCTION TO INHERITANCE $14.2 Figure type extent* display* FIGURE hierarchy barycenter* rotate* OPEN CLOSED FIGURE perimeter* FIGURE SEGMENT POLYLINE perimeter POLYGON ELLIPSE perimeter+ TRIANGLE diagonal QUADRANGLE CIRCLE perimeter+ perimeter+ RECTANGLE side1.side2 perimeter+ SQUARE
468 INTRODUCTION TO INHERITANCE §14.2 OPEN_ FIGURE SEGMENT POLYLINE POLYGON ELLIPSE QUADRANGLE CIRCLE TRIANGLE display* rotate* extent* … barycenter* … perimeter* perimeter+ diagonal SQUARE perimeter++ perimeter++ perimeter+ CLOSED_ FIGURE FIGURE perimeter RECTANGLE ++ side1, side2 ∗ ∗ ∗ Figure type hierarchy