15 Multiple inheritance lappicimrantxteshraworkefed in the preceding chapter.In study ing the basics of the mechanism we have encountered the notion that a class may need more than one parent.Known as multiple inheritance (to distinguish it from the more restrictive case of single inheritance),this possibility is necessary to build robust object-oriented architectures by combining different abstractions. Multiple inheritance,in its basic form,is a straightforward application of the principles of inheritance already seen;you just allow a class to include an arbitrary number of parents.More detailed probing brings up two interesting issues: The need for feature renaming,which in fact has useful applications in single inheritance too. The case of repeated inheritance,in which the ancestor relation links two classes in more than one way. 15.1 EXAMPLES OF MULTIPLE INHERITANCE The first task is to form a good idea of when multiple inheritance is useful.Let us study a few typical examples from many different backgrounds,a few will be shown in some detail,others only sketched. This review is all the more necessary that in spite of the elegance,necessity and fundamental simplicity of multiple inheritance,obvious to anyone who cares to study the concepts,this facility has sometimes been presented (often,as one later finds out,based solely on experience with languages or environments that cannot deal with it)as complex, mysterious,error-prone-as the object-oriented method's own"goto".Although it has no basis in either fact or theory,this view has been promoted widely enough to require that we take the time to review a host of cases in which multiple inheritance is indispensable. As it will turn out,the problem is not to think of valuable examples,but to stop the flow of examples that will start pouring in once we open the tap
15 Multiple inheritance Full application of inheritance requires an important extension to the framework defined in the preceding chapter. In studying the basics of the mechanism we have encountered the notion that a class may need more than one parent. Known as multiple inheritance (to distinguish it from the more restrictive case of single inheritance), this possibility is necessary to build robust object-oriented architectures by combining different abstractions. Multiple inheritance, in its basic form, is a straightforward application of the principles of inheritance already seen; you just allow a class to include an arbitrary number of parents. More detailed probing brings up two interesting issues: • The need for feature renaming, which in fact has useful applications in single inheritance too. • The case of repeated inheritance, in which the ancestor relation links two classes in more than one way. 15.1 EXAMPLES OF MULTIPLE INHERITANCE The first task is to form a good idea of when multiple inheritance is useful. Let us study a few typical examples from many different backgrounds; a few will be shown in some detail, others only sketched. This review is all the more necessary that in spite of the elegance, necessity and fundamental simplicity of multiple inheritance, obvious to anyone who cares to study the concepts, this facility has sometimes been presented (often, as one later finds out, based solely on experience with languages or environments that cannot deal with it) as complex, mysterious, error-prone — as the object-oriented method’s own “goto”. Although it has no basis in either fact or theory, this view has been promoted widely enough to require that we take the time to review a host of cases in which multiple inheritance is indispensable. As it will turn out, the problem is not to think of valuable examples, but to stop the flow of examples that will start pouring in once we open the tap
520 MULTIPLE INHERITANCE $15.1 What not to use as an introductory example To dispel a frequent confusion,we must first consider an example whose use(with some variants)by many introductory papers,books and lectures may account for some of the common mistrust of multiple inheritance.Not that there is anything fundamentally wrong with the example;it is simply inadequate for an introductory presentation,since it is not typical of simple,straightforward uses of multiple inheritance. The standard form of this example involves classes TEACHER and STUDENT,part of the model for some university system;you will be invited to note that some students are also teachers,prompting a new class TEACHING ASS/STAN7 that inherits from both TEACHER and STUDENT. A case of TEACHER STUDENT multiple inheritance... TEACHING ASSISTANT Is this example an improper use of inheritance?Not necessarily.But as an introduction to multiple inheritance it is about as bad as they can get.The problem is that TEACHER and STUDENT are not separate abstractions but variations on a common theme:person,or more accurately UNIVERSITY PERSON.So if we draw the full picture we see a case of not just multiple but repeated inheritance-the scheme,studied later in this chapter,in which a class is a proper descendant ofanother through two paths or more: UNIVERSITY ..that is a case PERSON of repeated inheritance TEACHER STUDENT TEACHING ASSISTANT Repeated inheritance is a special case;as will be noted when we get to it,using this Fordetails see facility requires good experience with the more elementary forms of inheritance,single and “REPEATED NHERITANCE” multiple.So it is not a matter for beginners,ifonly because it seems to create conflicts(what 15.4page543. about a feature name or subscribe to health plan which TEACHING ASSISTANT inherits
520 MULTIPLE INHERITANCE §15.1 What not to use as an introductory example To dispel a frequent confusion, we must first consider an example whose use (with some variants) by many introductory papers, books and lectures may account for some of the common mistrust of multiple inheritance. Not that there is anything fundamentally wrong with the example; it is simply inadequate for an introductory presentation, since it is not typical of simple, straightforward uses of multiple inheritance. The standard form of this example involves classes TEACHER and STUDENT, part of the model for some university system; you will be invited to note that some students are also teachers, prompting a new class TEACHING_ASSISTANT that inherits from both TEACHER and STUDENT. Is this example an improper use of inheritance? Not necessarily. But as an introduction to multiple inheritance it is about as bad as they can get. The problem is that TEACHER and STUDENT are not separate abstractions but variations on a common theme: person, or more accurately UNIVERSITY_PERSON. So if we draw the full picture we see a case of not just multiple but repeated inheritance — the scheme, studied later in this chapter, in which a class is a proper descendant of another through two paths or more: Repeated inheritance is a special case; as will be noted when we get to it, using this facility requires good experience with the more elementary forms of inheritance, single and multiple. So it is not a matter for beginners, if only because it seems to create conflicts (what about a feature name or subscribe_to_health_plan which TEACHING_ASSISTANT inherits A case of multiple inheritance… TEACHING_ ASSISTANT TEACHER STUDENT … that is a case of repeated inheritance TEACHING_ ASSISTANT UNIVERSITY_ PERSON TEACHER STUDENT For details see “REPEATED INHERITANCE”, 15.4, page 543
$15.1 EXAMPLES OF MULTIPLE INHERITANCE 521 from both of its parents,even though they are really in each case a single feature coming from the common ancestor UN/VERSITY PERSON?).With a well-reasoned approach we will be able to remove these conflicts simply.But it is a serious mistake to begin with such exceptional and seemingly tricky cases as if they were typical of multiple inheritance The truly common cases do not raise any such problem.Instead of dealing with variants of a single abstraction,they combine distinct abstractions.This is the form that you will need most often in building inheritance structures,and the one that introductory discussions should describe.The following examples belong to that pattern. Can an airplane be an asset? Our first proper example belongs to system modeling more than to software construction in the strict sense.But it is typical of situations that require multiple inheritance. Assume a class 4/RPLANE describing the abstraction suggested by its name. Queries may include passenger count,altitude,position,speed;commands may include take off,land,set speed. In a different domain,we may have a class ASSET describing the accounting notion of an asset-something which a company owns,although it may still be paying installments on it,and which it can depreciate or resell.Features may include purchase price, resale value,depreciate,resell,pay installment. You must have guessed where we are heading:companies may own company planes.For the pilot,a company plane is just a plane with its usual features:it takes off, lands,has a certain speed,flies somewhere.From the viewpoint of the accountant (the one who grumbles that the money would have been better kept in the bank or spent on more productive ventures)it is an asset,with a purchase value(too high),an estimated resale value (too low),and the need to pay interest on the loan each month. To model the notion of company plane we can resort to multiple inheritance: Company PLANE ASSET planes COMPANY PLANE class COMPANY PLANE inherit PLANE ASSET feature ..Any feature that is specific to company planes (rather than applying to all planes or all assets)... end
§15.1 EXAMPLES OF MULTIPLE INHERITANCE 521 from both of its parents, even though they are really in each case a single feature coming from the common ancestor UNIVERSITY_PERSON?). With a well-reasoned approach we will be able to remove these conflicts simply. But it is a serious mistake to begin with such exceptional and seemingly tricky cases as if they were typical of multiple inheritance. The truly common cases do not raise any such problem. Instead of dealing with variants of a single abstraction, they combine distinct abstractions. This is the form that you will need most often in building inheritance structures, and the one that introductory discussions should describe. The following examples belong to that pattern. Can an airplane be an asset? Our first proper example belongs to system modeling more than to software construction in the strict sense. But it is typical of situations that require multiple inheritance. Assume a class AIRPLANE describing the abstraction suggested by its name. Queries may include passenger_count, altitude, position, speed; commands may include take_off, land, set_speed. In a different domain, we may have a class ASSET describing the accounting notion of an asset — something which a company owns, although it may still be paying installments on it, and which it can depreciate or resell. Features may include purchase_price, resale_value, depreciate, resell, pay_installment. You must have guessed where we are heading: companies may own company planes. For the pilot, a company plane is just a plane with its usual features: it takes off, lands, has a certain speed, flies somewhere. From the viewpoint of the accountant (the one who grumbles that the money would have been better kept in the bank or spent on more productive ventures) it is an asset, with a purchase value (too high), an estimated resale value (too low), and the need to pay interest on the loan each month. To model the notion of company plane we can resort to multiple inheritance: class COMPANY_PLANE inherit PLANE ASSET feature … Any feature that is specific to company planes (rather than applying to all planes or all assets) … end Company planes COMPANY_ PLANE PLANE ASSET
522 MULTIPLE INHERITANCE $15.1 To specify multiple parents in the inherit clause,just list them one after the other. (As usual,you can use semicolons as optional separators.)The order in which you list parents is not significant. Cases similar to COMPANY PLANE abound in system modeling.Here are a few: Wristwatches (a special case of the notion of watch,itself specializing the general notion of clock-there are a few inheritance links here)provide commands such as setting the time,and queries such as the current time and date.Electronic calculators provide arithmetic features.There also exist some (quite handy)watch-calculators, elegantly modeled through multiple inheritance. Boats;trucks;AMPHIBIOUS VEHICLE.A variant is:boats;planes;HYDROPLANE (There is a hint of repeated inheritance here,as with TEACHING ASS/STANT,since both parents may themselves be descendants of some /EHICLE class.) You eat in a restaurant;you travel in a train car.To make your trip more enjoyable, the railway company may let you eat in an instance of EATING CAR.A variant of this example is SLEEPING CAR. On an instance of SOFA BED you may not only read but also sleep. .A MOBILE HOME is a VEHICLE and a HOUSE. And so on.Multiple inheritance is the natural tool to help model the endless combinations that astute people never tire of concocting. For a software engineer the preceding examples may at first appear academic,since we get paid not to model the world but to build systems.In many practical applications, however,you will encounter similar combinations of abstractions.A detailed example, from ISE's own graphical development environment appears later in this chapter. Numeric and comparable values The next example is much more directly useful to the daily practice of object-oriented software construction.It is essential to the buildup of the Kemel library. Some ofthe Kernel library's classes-that is to say,classes describing abstractions of potential use to all applications-require arithmetic features:operations such as infix "+"infix "-"infix"+",prefix "-"as well as special values ero (identity element for "+")and one (identity element for "*")Kernel library classes that use these features include INTEGER,REAL and DOUBLE;but many non-predefined classes may need them too,for example a class MATRIY describing matrices of some application-specific kind. It is appropriate to capture the corresponding abstraction through a deferred class NUMERIC,itself a part of the Kernel library: deferred class NUMER/C feature ..infix "+"infix "-"infix ""prefix ""zero,one .. end
522 MULTIPLE INHERITANCE §15.1 To specify multiple parents in the inherit clause, just list them one after the other. (As usual, you can use semicolons as optional separators.) The order in which you list parents is not significant. Cases similar to COMPANY_PLANE abound in system modeling. Here are a few: • Wristwatches (a special case of the notion of watch, itself specializing the general notion of clock — there are a few inheritance links here) provide commands such as setting the time, and queries such as the current time and date. Electronic calculators provide arithmetic features. There also exist some (quite handy) watch-calculators, elegantly modeled through multiple inheritance. • Boats; trucks; AMPHIBIOUS_VEHICLE. A variant is: boats; planes; HYDROPLANE. (There is a hint of repeated inheritance here, as with TEACHING_ASSISTANT, since both parents may themselves be descendants of some VEHICLE class.) • You eat in a restaurant; you travel in a train car. To make your trip more enjoyable, the railway company may let you eat in an instance of EATING_CAR. A variant of this example is SLEEPING_CAR. • On an instance of SOFA_BED you may not only read but also sleep. • A MOBILE_HOME is a VEHICLE and a HOUSE. And so on. Multiple inheritance is the natural tool to help model the endless combinations that astute people never tire of concocting. For a software engineer the preceding examples may at first appear academic, since we get paid not to model the world but to build systems. In many practical applications, however, you will encounter similar combinations of abstractions. A detailed example, from ISE’s own graphical development environment appears later in this chapter. Numeric and comparable values The next example is much more directly useful to the daily practice of object-oriented software construction. It is essential to the buildup of the Kernel library. Some of the Kernel library’s classes — that is to say, classes describing abstractions of potential use to all applications — require arithmetic features: operations such as infix "+", infix "–", infix "∗", prefix "–" as well as special values zero (identity element for "+") and one (identity element for "∗"). Kernel library classes that use these features include INTEGER, REAL and DOUBLE; but many non-predefined classes may need them too, for example a class MATRIX describing matrices of some application-specific kind. It is appropriate to capture the corresponding abstraction through a deferred class NUMERIC, itself a part of the Kernel library: deferred class NUMERIC feature … infix "+", infix "–", infix "∗", prefix "–", zero, one … end
$15.1 EXAMPLES OF MULTIPLE INHERITANCE 523 Mathematically,NUMER/C has a precise specification:its instances represent members of a ring(a set equipped with two operations,both of which separately give it the structure of a group,one commutative,with distributivity between the two operations). Some classes also need an order relation,with features for comparing arbitrary elements:infix "",infix ">="Again this is useful not only to some Kernel library classes,such as STR/NG whose instances are comparable through lexical ordering,but also to many application classes;for example you may write a class TENNIS CHAMP/ON which takes into account the ranking of professional tennis players, with a feature "",infix ">=".. end Technically the COMPAR4BLE has a precise mathematical model:its instances represent members exact model is that of a set ordered by a total order relation. ofa"preorder” Notall descendants ofCOMPARABLE should be descendants of NUMER/C:in class STRING,we need the order features for lexicographical ordering but not the arithmetic features.Conversely,not all descendants of NUMER/C should be descendants of COMPARABLE:the set of real matrices has addition,multiplication,zero and one,giving it a ring structure,but no total order relation.So it is appropriate that COMPARABLE and NUMER/C,representing completely different abstractions,should remain distinct classes, neither of them a descendant of the other. Objects of certain types,however,are both comparable and numeric.(In mathematical terms.the structures modeled by their generating classes are totally ordered rings.)Example classes include REAL and INTEGER:integers and real numbers can be compared for "<="as well as added and multiplied.These classes should be defined through multiple inheritance,as in(see the figure on the next page): expanded class REAL inherit NUMERIC COMPARABLE feature end Types of objects that need to be both comparable and numeric are sufficiently common to suggest a class COMPARABLE NUMER/C,still deferred,covering the merged abstraction by multiply inheriting from COMPARABLE and NUMER/C.So far this solution has not been adopted for the library because it does not bring any obvious ad vantage and seems to open the way to endless combinations:why not COMPARABLE HASHABLE,HASHA BLE ADDABLE SUBTRACTABLE?Basing such deferred classes on well-accepted mathematical abstractions,such as ring or totally ordered set,seems to yield the right level of granularity.Related issues in the methodology of inheritance are discussed in detail in chapter 16
§15.1 EXAMPLES OF MULTIPLE INHERITANCE 523 Mathematically, NUMERIC has a precise specification: its instances represent members of a ring (a set equipped with two operations, both of which separately give it the structure of a group, one commutative, with distributivity between the two operations). Some classes also need an order relation, with features for comparing arbitrary elements: infix "", infix ">=". Again this is useful not only to some Kernel library classes, such as STRING whose instances are comparable through lexical ordering, but also to many application classes; for example you may write a class TENNIS_CHAMPION which takes into account the ranking of professional tennis players, with a feature "", infix ">=" … end COMPARABLE has a precise mathematical model: its instances represent members of a set ordered by a total order relation. Not all descendants of COMPARABLE should be descendants of NUMERIC: in class STRING, we need the order features for lexicographical ordering but not the arithmetic features. Conversely, not all descendants of NUMERIC should be descendants of COMPARABLE: the set of real matrices has addition, multiplication, zero and one, giving it a ring structure, but no total order relation. So it is appropriate that COMPARABLE and NUMERIC, representing completely different abstractions, should remain distinct classes, neither of them a descendant of the other. Objects of certain types, however, are both comparable and numeric. (In mathematical terms. the structures modeled by their generating classes are totally ordered rings.) Example classes include REAL and INTEGER: integers and real numbers can be compared for "<=" as well as added and multiplied. These classes should be defined through multiple inheritance, as in (see the figure on the next page): expanded class REAL inherit NUMERIC COMPARABLE feature … end Types of objects that need to be both comparable and numeric are sufficiently common to suggest a class COMPARABLE_NUMERIC, still deferred, covering the merged abstraction by multiply inheriting from COMPARABLE and NUMERIC. So far this solution has not been adopted for the library because it does not bring any obvious advantage and seems to open the way to endless combinations: why not COMPARABLE_ HASHABLE, HASHABLE_ADDABLE_SUBTRACTABLE? Basing such deferred classes on well-accepted mathematical abstractions, such as ring or totally ordered set, seems to yield the right level of granularity. Related issues in the methodology of inheritance are discussed in detail in chapter 16. Technically the exact model is that of a “preorder
524 MULTIPLE INHERITANCE $15.1 Multiple COMPARABLE NUMERIC structure inheritance INTEGER REAL DOUBLE Windows are trees and rectangles Assume a window system that allows nesting windows to an arbitrary depth: Windows and subwindows In the corresponding class WINDOW,we will find features of two general kinds: Some deal with a window as a member of a hierarchical structure:list of subwindows,parent window,number of subwindows,add or remove a subwindow. Others cover its properties as a graphical object occupying a graphical area:height, width,x position,y position,display,hide,translate
524 MULTIPLE INHERITANCE §15.1 Windows are trees and rectangles Assume a window system that allows nesting windows to an arbitrary depth: In the corresponding class WINDOW, we will find features of two general kinds: • Some deal with a window as a member of a hierarchical structure: list of subwindows, parent window, number of subwindows, add or remove a subwindow. • Others cover its properties as a graphical object occupying a graphical area: height, width, x position, y position, display, hide, translate. INTEGER COMPARABLE NUMERIC REAL DOUBLE Multiple structure inheritance Windows and subwindows
$15.1 EXAMPLES OF MULTIPLE INHERITANCE 525 It is possible to write the class as a single piece,with all these features mixed together.But this would be bad design.To keep the structure manageable we should separate the two aspects,treating class WINDOW as the combination of two abstractions: Hierarchical structures,which should be covered by a class TREE. Rectangular screen objects,covered by a class RECTANGLE. In practice we may need more specific class names(describing some particular category of trees,and a graphical rather than purely geometrical notion of rectangle),but the ones above will be convenient for this discussion.WINDOW will appear as: class WINDOW inherit TREE [WINDOW] RECTANGLE feature ..Specific window features... end Note that class TREE will be generic,so we need to specify an actual generic parameter,here WINDOW itself.The recursive nature of this definition reflects the recursion in the situation modeled:a window is a tree of windows. This example will,later on in the discussion,help us understand the need for a feature renaming mechanism associated with inheritance. A further refinement might follow from the observation that some windows are purely text windows.Although we might represent this property by introducing a class TEXT WINDOW as a client of STR/NG with an attribute text:STRING we may prefer to consider that each text window is also a string.In this case we will use multiple inheritance from WINDOW and STR/NG.(If all windows of interest are text windows,we might directly use triple inheritance from TREE,RECTANGLE and STRING,although even in that case it is probably better to work in two successive stages. See“WOULD YOU The general question of how to choose between heir and client relations,as in the RATHER BUY OR INHERIT?”,24.2 case of TEXT WINDOW,is discussed in detail in the chapter on inheritance methodology. page 812. Trees are lists and list elements Class TREE itself provides a striking example of multiple inheritance. A tree is a hierarchical structure made of nodes,each containing some information. Common definitions tend to be of the form "A tree is either empty or contains an object called the root,together with(recursively)a list of trees,called the children of the root", complemented by a definition of node,such as"An empty tree has no nodes;the nodes of a non-empty tree comprise its root and (recursively)the nodes of its children".Although useful,and reflective of the recursiveness inherent in the notion of tree,these definitions fail to capture its essential simplicity
§15.1 EXAMPLES OF MULTIPLE INHERITANCE 525 It is possible to write the class as a single piece, with all these features mixed together. But this would be bad design. To keep the structure manageable we should separate the two aspects, treating class WINDOW as the combination of two abstractions: • Hierarchical structures, which should be covered by a class TREE. • Rectangular screen objects, covered by a class RECTANGLE. In practice we may need more specific class names (describing some particular category of trees, and a graphical rather than purely geometrical notion of rectangle), but the ones above will be convenient for this discussion. WINDOW will appear as: class WINDOW inherit TREE [WINDOW] RECTANGLE feature … Specific window features … end Note that class TREE will be generic, so we need to specify an actual generic parameter, here WINDOW itself. The recursive nature of this definition reflects the recursion in the situation modeled: a window is a tree of windows. This example will, later on in the discussion, help us understand the need for a feature renaming mechanism associated with inheritance. A further refinement might follow from the observation that some windows are purely text windows. Although we might represent this property by introducing a class TEXT_WINDOW as a client of STRING with an attribute text: STRING we may prefer to consider that each text window is also a string. In this case we will use multiple inheritance from WINDOW and STRING. (If all windows of interest are text windows, we might directly use triple inheritance from TREE, RECTANGLE and STRING, although even in that case it is probably better to work in two successive stages.) The general question of how to choose between heir and client relations, as in the case of TEXT_WINDOW, is discussed in detail in the chapter on inheritance methodology. Trees are lists and list elements Class TREE itself provides a striking example of multiple inheritance. A tree is a hierarchical structure made of nodes, each containing some information. Common definitions tend to be of the form “A tree is either empty or contains an object called the root, together with (recursively) a list of trees, called the children of the root”, complemented by a definition of node, such as “An empty tree has no nodes; the nodes of a non-empty tree comprise its root and (recursively) the nodes of its children”. Although useful, and reflective of the recursiveness inherent in the notion of tree, these definitions fail to capture its essential simplicity. See “WOULD YOU RATHER BUY OR INHERIT?”, 24.2, page 812
526 MULTIPLE INHERITANCE $15.1 To get a different perspective,observe that there is no significant distinction between the notion of tree and that ofnode,as we may identify a node with the subtree of which it is the root.This suggests aiming for a class TREE [G]that describes both trees and nodes. The formal generic parameter G represents the type of information attached to every node; the tree below,for example,is an instance of TREE [INTEGER]. 89 A tree of integers 235 30 0 5 1000 Now consider a notion of L/S7,with a class that has been sketched in earlier chapters.A general implementation (linked,for example)will need an auxiliary class CELL to describe the individual elements of a list. LIST (CELL) These notions suggest a simple definition of trees:a tree (or tree node)is a list,the list of its children;but it is also a potential list element,as it can be made into a subtree of another tree. Definition:tree A tree is a list that is also a list element. Although this definition would need some refinement to achieve full mathematical rigor,it directly yields a class definition: deferred class TREE [G]inherit LIST G] CELL [G] feature end From L/ST come the features to find out the number of children (counr),add a child, remove a child and so on. From CELL come the features having to do with a node's siblings and parents:next sibling,add a sibling,reattach to a different parent node
526 MULTIPLE INHERITANCE §15.1 To get a different perspective, observe that there is no significant distinction between the notion of tree and that of node, as we may identify a node with the subtree of which it is the root. This suggests aiming for a class TREE [G] that describes both trees and nodes. The formal generic parameter G represents the type of information attached to every node; the tree below, for example, is an instance of TREE [INTEGER]. Now consider a notion of LIST, with a class that has been sketched in earlier chapters. A general implementation (linked, for example) will need an auxiliary class CELL to describe the individual elements of a list. These notions suggest a simple definition of trees: a tree (or tree node) is a list, the list of its children; but it is also a potential list element, as it can be made into a subtree of another tree. Although this definition would need some refinement to achieve full mathematical rigor, it directly yields a class definition: deferred class TREE [G] inherit LIST [G] CELL [G] feature … end From LIST come the features to find out the number of children (count), add a child, remove a child and so on. From CELL come the features having to do with a node’s siblings and parents: next sibling, add a sibling, reattach to a different parent node. Definition: tree A tree is a list that is also a list element. A tree of integers 89 235 –2 30 –1 0 5 1000 (CELL) LIST
$15.1 EXAMPLES OF MULTIPLE INHERITANCE 527 This example is typical of the reusability benefits of multiple inheritance.Writing specific features for subtree insertion or removal would needlessly replicate the work done for lists.Writing specific features for sibling and parent operations would needlessly replicate the work done for list elements.Only a facelift is needed in each case. In addition you will have to take care,in the feature clause,of the specific features of trees and of the little mutual compromises which,as in any marriage,are necessary to ensure that life together is harmonious and prolific.In a class TREE derived from these ideas,which has been used in many different applications(from graphics to structural editing),these specific features fit on little more than a page;for the most part,the class is simply engendered as the legitimate fruit of the union between lists and list elements. This process is exactly that used in mathematics to combine theories:a topological vector space,for example,is a vector space that also is a topological space;here too,some connecting axioms need to be added to finish up the merger. Composite figures The following example is more than an example;it is a design pattern useful in many different contexts. Consider an inheritance structure containing classes for various graphical figures, such as the one used in the preceding chapter to introduce some of the fundamental concepts of inheritance FIGURE,OPEN FIGURE,POLYGON,RECTANGLE, ELL/PSE and so on.So far,as you may have noted,that structure used single inheritance Assume that we have included in this hierarchy all the basic figure patterns that we need.That is not enough yet:many figures are not basic.Of course we could build any graphical illustration from elementary shapes,but that is not a convenient way to work; instead,we will want to build ourselves alibrary of figures,some basic,some constructed from the basic ones.For example,from basic segment and circle figures Elementary figures we may assemble a composite figure,representing a wheel A composite figure which someone may in turn use as a predefined pattern to draw,say,a bicycle;and so on
§15.1 EXAMPLES OF MULTIPLE INHERITANCE 527 This example is typical of the reusability benefits of multiple inheritance. Writing specific features for subtree insertion or removal would needlessly replicate the work done for lists. Writing specific features for sibling and parent operations would needlessly replicate the work done for list elements. Only a facelift is needed in each case. In addition you will have to take care, in the feature clause, of the specific features of trees and of the little mutual compromises which, as in any marriage, are necessary to ensure that life together is harmonious and prolific. In a class TREE derived from these ideas, which has been used in many different applications (from graphics to structural editing), these specific features fit on little more than a page; for the most part, the class is simply engendered as the legitimate fruit of the union between lists and list elements. This process is exactly that used in mathematics to combine theories: a topological vector space, for example, is a vector space that also is a topological space; here too, some connecting axioms need to be added to finish up the merger. Composite figures The following example is more than an example; it is a design pattern useful in many different contexts. Consider an inheritance structure containing classes for various graphical figures, such as the one used in the preceding chapter to introduce some of the fundamental concepts of inheritance — FIGURE, OPEN_FIGURE, POLYGON, RECTANGLE, ELLIPSE and so on. So far, as you may have noted, that structure used single inheritance. Assume that we have included in this hierarchy all the basic figure patterns that we need. That is not enough yet: many figures are not basic. Of course we could build any graphical illustration from elementary shapes, but that is not a convenient way to work; instead, we will want to build ourselves a library of figures, some basic, some constructed from the basic ones. For example, from basic segment and circle figures we may assemble a composite figure, representing a wheel which someone may in turn use as a predefined pattern to draw, say, a bicycle; and so on. Elementary figures A composite figure
528 MULTIPLE INHERITANCE $15.1 We need a general mechanism for adding a new figure type which will be built from previously defined ones but,once defined,will be on a par with them.Computer drawing tools provide a Group command for this purpose. Let us call the corresponding notion COMPOSITE FIGURE.A composite figure is clearly a figure;so COMPOSITE FIGURE should inherit from F/GURE,achieving the goal of treating composite figures"on a par"with basic ones.A composite figure is also a list of figures-its constituents;each of them may be basic or itself composite.Hence the use of multiple inheritance: A composite extent* display* FIGURE LINKED LIST figure is a barycenter* rotate* figure and a list of figures COMPOSITE OPEN CLOSED FIGURE perimeter* FIGURE FIGURE SEGMENT POLYLINE perinteter POLYGON ELLIPSE TRIANGLE diagonal OUADRANGLE CIRCLE perimeter perimeter BASIC sidel,side2 RECTANGLE FIGURES (see previous chapter) perimeter SQUARE To get an effective class for COMPOSITE F/GURE we choose an implementation of lists;LINKED L/ST is just one possibility.The class declaration will look like this:
528 MULTIPLE INHERITANCE §15.1 We need a general mechanism for adding a new figure type which will be built from previously defined ones but, once defined, will be on a par with them. Computer drawing tools provide a Group command for this purpose. Let us call the corresponding notion COMPOSITE_FIGURE. A composite figure is clearly a figure; so COMPOSITE_FIGURE should inherit from FIGURE, achieving the goal of treating composite figures “on a par” with basic ones. A composite figure is also a list of figures — its constituents; each of them may be basic or itself composite. Hence the use of multiple inheritance: To get an effective class for COMPOSITE_FIGURE we choose an implementation of lists; LINKED_LIST is just one possibility. The class declaration will look like this: A composite figure is a figure and a list of figures OPEN_ FIGURE SEGMENT POLYLINE POLYGON ELLIPSE QUADRANGLE TRIANGLE CIRCLE display* rotate* extent* … barycenter* perimeter* perimeter+ diagonal SQUARE perimeter++ perimeter++ perimeter+ CLOSED_ FIGURE FIGURE RECTANGLE perimeter++ side1, side2 ∗ ∗ ∗ COMPOSITE_ FIGURE LINKED_LIST BASIC FIGURES (see previous chapter)