824 USING INHERITANCE PROPERLY $24.5 APPLE and from PIE,or(this one reported by Adele Goldberg)ROSE TREE inheriting from ROSE and from TREE. Another is a typical case of taxomania in which a simple boolean property,such as a person's gender(or a property with a few fixed values,such as the color of a traffic light) is used as an inheritance criterion even though no significant feature variants depend on it. A third typical mistake is convenience inheritance,in which the developer sees some useful features in a class and inherits from that class simply to reuse these features. What is wrong here is neither the act of "using inheritance for implementation",nor "inheriting a class for its features",both of which are acceptable forms of inheritance studied later in this chapter,but the use of a class as a parent without the proper is-a relationship between the corresponding abstractions-or in some cases without adequate abstractions at all. General taxonomy On now to the valid uses of inheritance.The list will include twelve different categories, conveniently grouped into three broad families: Valid use of inheritance Classification of the valid categories of Model inheritance inheritance Variation Software inheritance inheritance Subtype inheritance Facility Reification inheritance inheritance View inheritance Extension ● inheritance Structure ● inheritance Constant inheritance Restriction inheritance Implementation ● inheritance Machine Functional Type Uneffecting inheritance variation variation inheritance inheritance inheritance
824 USING INHERITANCE PROPERLY §24.5 APPLE and from PIE, or (this one reported by Adele Goldberg) ROSE_TREE inheriting from ROSE and from TREE. Another is a typical case of taxomania in which a simple boolean property, such as a person’s gender (or a property with a few fixed values, such as the color of a traffic light) is used as an inheritance criterion even though no significant feature variants depend on it. A third typical mistake is convenience inheritance, in which the developer sees some useful features in a class and inherits from that class simply to reuse these features. What is wrong here is neither the act of “using inheritance for implementation”, nor “inheriting a class for its features”, both of which are acceptable forms of inheritance studied later in this chapter, but the use of a class as a parent without the proper is-a relationship between the corresponding abstractions — or in some cases without adequate abstractions at all. General taxonomy On now to the valid uses of inheritance. The list will include twelve different categories, conveniently grouped into three broad families: Classification of the valid categories of inheritance Valid use of inheritance Software inheritance Model inheritance Subtype inheritance Restriction inheritance Extension inheritance Variation inheritance Functional variation inheritance Type variation inheritance View inheritance Reification inheritance Structure inheritance Implementation inheritance Facility inheritance Constant inheritance Machine inheritance Uneffecting inheritance
$24.5 USING INHERITANCE:A TAXONOMY OF TAXONOMY 825 The classification is based on the observation that any software system reflects a certain external model,itself connected with some outside reality in the software's application domain.Then we may distinguish: Model inheritance,reflecting "is-a"relations between abstractions in the model. Software inheritance,expressing relations within the software,with no obvious counterpart in the model. Variation inheritance-a special case that may pertain either to the software or to the model-serving to describe a class through its differences with another class. These three general categories facilitate understanding,but the most important properties are captured by the final categories(the tree leaves on the preceding figure). Exercise E24.2. Since the classification is itself a taxonomy,you may want to ask yourself,out of page 869. curiosity,how the identified categories apply to it.This is the topic of an exercise. The definitions which follow all use the names 4 for the parent class and B for the heir. Naming convention for definitions of inheritance categories Each definition will state which of4 and B is permitted to be deferred,and which effective.A table at the end of the discussion recalls the applicable categories for each deferred-effective com bination. Subtype inheritance We start with the most obvious form of model inheritance.You are modeling some external system where a category of(external)objects can be partitioned into disjoint subcategories-as with closed figures,partitioned into polygons,ellipses etc.-and you use inheritance to organize the corresponding classes in the software.A bit more formally: Definition:subtype inheritance Subtype inheritance applies if4 and B represent certain sets 'and B'of external objects such that B'is a subset of 'and the set modeled by any other subtype heir ofA is disjoint from B.A must be deferred. 4'could be the set of closed figures,B the set of polygons,4 and B the corresponding classes.In most practical cases the"external system"will be non-software, for example some aspect of a company's business(where the extemal objects might be checking and savings accounts)or some part of the physical world(where they might be planets and stars)
§24.5 USING INHERITANCE: A TAXONOMY OF TAXONOMY 825 The classification is based on the observation that any software system reflects a certain external model, itself connected with some outside reality in the software’s application domain. Then we may distinguish: • Model inheritance, reflecting “is-a” relations between abstractions in the model. • Software inheritance, expressing relations within the software, with no obvious counterpart in the model. • Variation inheritance — a special case that may pertain either to the software or to the model — serving to describe a class through its differences with another class. These three general categories facilitate understanding, but the most important properties are captured by the final categories (the tree leaves on the preceding figure). Since the classification is itself a taxonomy, you may want to ask yourself, out of curiosity, how the identified categories apply to it. This is the topic of an exercise. The definitions which follow all use the names A for the parent class and B for the heir. Each definition will state which of A and B is permitted to be deferred, and which effective. A table at the end of the discussion recalls the applicable categories for each deferred-effective combination. Subtype inheritance We start with the most obvious form of model inheritance. You are modeling some external system where a category of (external) objects can be partitioned into disjoint subcategories — as with closed figures, partitioned into polygons, ellipses etc. — and you use inheritance to organize the corresponding classes in the software. A bit more formally: A' could be the set of closed figures, B' the set of polygons, A and B the corresponding classes. In most practical cases the “external system” will be non-software, for example some aspect of a company’s business (where the external objects might be checking and savings accounts) or some part of the physical world (where they might be planets and stars). Definition: subtype inheritance Subtype inheritance applies if A and B represent certain sets A' and B' of external objects such that B' is a subset of A' and the set modeled by any other subtype heir of A is disjoint from B'. A must be deferred. Exercise E24.2, page 869. Naming convention for definitions of inheritance categories B A
826 USING INHERITANCE PROPERLY $24.5 Subtype inheritance is the form of inheritance that is closest to the hierarchical taxonomies of botany,zoology and other natural sciences(VERTEBRATEMAMMAL and the like).A typical software example (other than closed figures and polygons)is DEVICEFILE.We insist that the parent,4,be deferred,so that it describes a non- completely specified set of objects.B,the heir,may be effective,or it may still be deferred. The next two categories cover the case in which 4 may be effective. A later section will explore in more detail this inheritance category,not always as “SUBTYPE INHER- straightforward as it would seem at first. ITANCE AND DESCENDANT Restriction inheritance HDNG”,24.7, page 835. Definition:restriction inheritance Restriction inheritance applies if the instances of B are those instances of that satisfy a certain constraint,expressed if possible as part of the invariant of B and not included in the invariant of 4.Any feature introduced by B should be a logical consequence of the added constraint.4 and B should be both deferred or both effective. Typical examples are RECTANGLESOUARE,where the extra constraint is side /side2 (included in the invariant of SOUARE),and ELLIPSECIRCLE,where the extra constraint is that the two focuses (or foci)of an ellipse are the same point for a circle in the general case an ellipse is the set of points such that the sum of their distances to the two focuses is equal to a certain constant.Many mathematical examples indeed fall into this category. The last part of the definition is meant to avoid mixing this form of inheritance with others,such as extension inheritance,which may add completely new features in the heir. Here to keep things simple it is preferable to limit new features,if any,to those that directly follow from the added constraint.For example class C/RCLE will have a new feature radius which satisfies this property:in a circle,all points have the same distance from the merged center,and this distance deserves the status of a feature of the class, whereas the corresponding notion in class ELL/PSE(the average of the distances to the two focuses)was probably not considered significant enough to yield a feature. Because the only conceptual change from A to B is to add some constraints,the classes should be both deferred or both effective. Restriction inheritance is conceptually close to subtype inheritance;the later discussion of subtyping will for the most part apply to both categories. Extension inheritance Definition:extension inheritance Extension inheritance applies when B introduces features not present in A and not applicable to direct instances of 4.Class must be effective
826 USING INHERITANCE PROPERLY §24.5 Subtype inheritance is the form of inheritance that is closest to the hierarchical taxonomies of botany, zoology and other natural sciences (VERTEBRATE MAMMAL and the like). A typical software example (other than closed figures and polygons) is DEVICE FILE. We insist that the parent, A, be deferred, so that it describes a noncompletely specified set of objects. B, the heir, may be effective, or it may still be deferred. The next two categories cover the case in which A may be effective. A later section will explore in more detail this inheritance category, not always as straightforward as it would seem at first. Restriction inheritance Typical examples are RECTANGLE SQUARE, where the extra constraint is side1 = side2 (included in the invariant of SQUARE), and ELLIPSE CIRCLE, where the extra constraint is that the two focuses (or foci) of an ellipse are the same point for a circle ; in the general case an ellipse is the set of points such that the sum of their distances to the two focuses is equal to a certain constant. Many mathematical examples indeed fall into this category. The last part of the definition is meant to avoid mixing this form of inheritance with others, such as extension inheritance, which may add completely new features in the heir. Here to keep things simple it is preferable to limit new features, if any, to those that directly follow from the added constraint. For example class CIRCLE will have a new feature radius which satisfies this property: in a circle, all points have the same distance from the merged center, and this distance deserves the status of a feature of the class, whereas the corresponding notion in class ELLIPSE (the average of the distances to the two focuses) was probably not considered significant enough to yield a feature. Because the only conceptual change from A to B is to add some constraints, the classes should be both deferred or both effective. Restriction inheritance is conceptually close to subtype inheritance; the later discussion of subtyping will for the most part apply to both categories. Extension inheritance Definition: restriction inheritance Restriction inheritance applies if the instances of B are those instances of A that satisfy a certain constraint, expressed if possible as part of the invariant of B and not included in the invariant of A. Any feature introduced by B should be a logical consequence of the added constraint. A and B should be both deferred or both effective. Definition: extension inheritance Extension inheritance applies when B introduces features not present in A and not applicable to direct instances of A. Class A must be effective. “SUBTYPE INHERITANCE AND DESCENDANT HIDING”, 24.7, page 835
$24.5 USING INHERITANCE:A TAXONOMY OF TAXONOMY 827 The presence of both the restriction and extension variants is one of the paradoxes of inheritance.As noted in the discussion of inheritance,extension applies to features whereas restriction (and more generally specialization)applies to instances,but this does not completely eliminate the paradox. The problem is that the added features will usually include attributes.So if we take the naive interpretation of a type (as given by a class)as the set of its instances,then it seems the subset relation is the wrong way around!Assume for example class A feature al:INTEGER end class B inherit A feature bl:REAL end Non-mathematical Then if we view each instance of 4 as representing a singleton,that is to say a set readers may skip this containing one integer(which we can write as<n>where n is the chosen integer)and each one paragraph. instance of B as a pair containing an integer and a real (such as the pair<1,-2.5>),the set of pairs MB is not a subset of the set of singletons M4.In fact,if we absolutely want a subset relation,it will be in the reverse direction:there is a one-to-one mapping between MA and the set of all pairs having a given second element,for example 0.0. This discovery that the subset relation seems to be the wrong way may make extension inheritance look suspicious.For example an early version of a respected O-O library (not from ISE)had RECTANGLE inheriting from SOUARE,not the other way around as we have learned.The reasoning was simple:SOUARE has a side attribute; RECTANGLE inherits from SOUARE and adds a new feature,other side,so here is an inheritance link for you!Several people criticized the design and it was soon reversed. But we cannot dismiss the general category of extension inheritance.In fact its equivalent in mathematics,where you specialize a certain notion by adding completely new operations,is frequently used and considered quite necessary.A typical example is the notion of ring,specializing the notion of group.A group has a certain operation,say +with certain properties.A ring is a group,so it also has with these properties,but it adds a new operation,say *with extra properties of its own.This is not fundamentally different from introducing a new attribute in an heir software class. The corresponding scheme is frequent in O-O software too.In most applications,of course,SOUARE should inherit from RECTANGLE,not the reverse;but it is not difficult to think of legitimate examples.A class MOVING POINT (for kinematics applications) might inherit from a purely graphical class POINT and add a feature speed describing the speed's magnitude and direction;or,in a text processing application,a class CHAPTER might inherit from DOCUMEN7,adding the specific features of a document which is a chapter in a book,such as its current position in the book and a procedure that will reposition it
§24.5 USING INHERITANCE: A TAXONOMY OF TAXONOMY 827 The presence of both the restriction and extension variants is one of the paradoxes of inheritance. As noted in the discussion of inheritance, extension applies to features whereas restriction (and more generally specialization) applies to instances, but this does not completely eliminate the paradox. The problem is that the added features will usually include attributes. So if we take the naïve interpretation of a type (as given by a class) as the set of its instances, then it seems the subset relation is the wrong way around! Assume for example class A feature a1: INTEGER end class B inherit A feature b1: REAL end Then if we view each instance of A as representing a singleton, that is to say a set containing one integer (which we can write as <n> where n is the chosen integer) and each instance of B as a pair containing an integer and a real (such as the pair <1, –-2.5>), the set of pairs MB is not a subset of the set of singletons MA. In fact, if we absolutely want a subset relation, it will be in the reverse direction: there is a one-to-one mapping between MA and the set of all pairs having a given second element, for example 0.0. This discovery that the subset relation seems to be the wrong way may make extension inheritance look suspicious. For example an early version of a respected O-O library (not from ISE) had RECTANGLE inheriting from SQUARE, not the other way around as we have learned. The reasoning was simple: SQUARE has a side attribute; RECTANGLE inherits from SQUARE and adds a new feature, other_side, so here is an inheritance link for you! Several people criticized the design and it was soon reversed. But we cannot dismiss the general category of extension inheritance. In fact its equivalent in mathematics, where you specialize a certain notion by adding completely new operations, is frequently used and considered quite necessary. A typical example is the notion of ring, specializing the notion of group. A group has a certain operation, say +, with certain properties. A ring is a group, so it also has + with these properties, but it adds a new operation, say ∗, with extra properties of its own. This is not fundamentally different from introducing a new attribute in an heir software class. The corresponding scheme is frequent in O-O software too. In most applications, of course, SQUARE should inherit from RECTANGLE, not the reverse; but it is not difficult to think of legitimate examples. A class MOVING_POINT (for kinematics applications) might inherit from a purely graphical class POINT and add a feature speed describing the speed’s magnitude and direction; or, in a text processing application, a class CHAPTER might inherit from DOCUMENT, adding the specific features of a document which is a chapter in a book, such as its current position in the book and a procedure that will reposition it. Non-mathematical readers may skip this one paragraph
828 USING INHERITANCE PROPERLY $24.5 A proper mathematical model (Non-mathematically-inclined readers should skip this section. For peace of mind we must resolve the apparent paradox noted earlier(the discovery that MB is not a subset of M4)since we do want some subset relation to hold between instances of an heir and instances of the parent.That relation does exist in the case of extension inheritance;what the paradox shows is that it is inappropriate to use cartesian product of the attribute types to model a class.Given a class class C feature cl:Tl c2:T2 c3:T3 end we should not take,as a mathematical model C'for the set of instances ofC,the cartesian product T/x T2 x T3,where the prime signs indicate that we recursively use the model sets;this would lead to the paradox(among other disadvantages). Instead,we should consider any instance as being a partial function from the set of The fimctions of possible attribute names ATTR/BUTE to the set of all possible values VALUE,with the interest are not only following properties: partial but fmite. Al.The function is defined for c/,c2 and c3. A2.The set VALUE (the target set of the function)is a superset of T/UT2 U T3. A3.The function's value for c/is in T/,and so on. Then if we remember that a function is a special case of a relation,and that a relation is a set of pairs (for example an instance of class 4 may be modeled by the function (<al,25>),and the instance of B cited on the preceding page by <al,I>,<bl, -2.5>)),then we do have the expected property that B'is a subset of 4. Note that it is essential to state the property Al as "The function is defined for...",not "The function's domain is..."which would limit the domain to the set (cl,c2 c3), preventing descendants from adding their own attributes.As a result of this approach, every software object is modeled by an infinity of(finite)mathematical objects. This discussion has only given a sketch of the mathematical model.For more details on using partial functions to model tuples,and the general mathematical background,see [M19901- Variation inheritance (Non-mathematical readers,welcome back!)We now move to the second of our three broad groups of inheritance categories:variation inheritance
828 USING INHERITANCE PROPERLY §24.5 A proper mathematical model (Non-mathematically-inclined readers should skip this section.) For peace of mind we must resolve the apparent paradox noted earlier (the discovery that MB is not a subset of MA) since we do want some subset relation to hold between instances of an heir and instances of the parent. That relation does exist in the case of extension inheritance; what the paradox shows is that it is inappropriate to use cartesian product of the attribute types to model a class. Given a class class C feature c1: T1 c2: T2 c3: T3 end we should not take, as a mathematical model C' for the set of instances of C, the cartesian product T'1 × T'2 × T'3, where the prime signs ' indicate that we recursively use the model sets; this would lead to the paradox (among other disadvantages). Instead, we should consider any instance as being a partial function from the set of possible attribute names ATTRIBUTE to the set of all possible values VALUE, with the following properties: A1 • The function is defined for c1, c2 and c3. A2 • The set VALUE (the target set of the function) is a superset of T'1 ∪ T'2 ∪ T'3. A3 • The function’s value for c1 is in T'1, and so on. Then if we remember that a function is a special case of a relation, and that a relation is a set of pairs (for example an instance of class A may be modeled by the function {<a1, 25>}, and the instance of B cited on the preceding page by {<a1, 1>, <b1, –2.5>}), then we do have the expected property that B' is a subset of A. Note that it is essential to state the property A1 as “The function is defined for…”, not “The function’s domain is…” which would limit the domain to the set {c1, c2 c3}, preventing descendants from adding their own attributes. As a result of this approach, every software object is modeled by an infinity of (finite) mathematical objects. This discussion has only given a sketch of the mathematical model. For more details on using partial functions to model tuples, and the general mathematical background, see [M 1990]. Variation inheritance (Non-mathematical readers, welcome back!) We now move to the second of our three broad groups of inheritance categories: variation inheritance. The functions of interest are not only partial but finite