<<

-based Inheritance

Gilad Bracha∗ William Cook Department of Computer Science Hewlett-Packard Laboratories University of Utah 1501 Page Mill Road Salt Lake City, UT 84112 Palo Alto, CA 94303-0969

Abstract prefix methods cannot be replaced; instead, the prefix may use the command inner to invoke the extended The diverse inheritance mechanisms provided by method code supplied by the subpattern. Given that the , Beta, and CLOS are interpreted as differ- code in a prefix is executed in any of its extensions, Beta ent uses of a single underlying construct. Smalltalk and enforces a degree of behavioral consistency between a Beta differ primarily in the direction of class hierarchy pattern and its subpatterns. growth. These inheritance mechanisms are subsumed in The underlying mechanism of inheritance is the same a new inheritance model based on composition of mix- for Beta and Smalltalk [3]. The difference between them ins, or abstract subclasses. This form of inheritance lies in whether the extensions to an existing definition can also encode a CLOS multiple-inheritance hierarchy, have precedence over and may refer to previous defini- although changes to the encoded hierarchy that would tions (Smalltalk), or the inherited definition has prece- violate encapsulation are difficult. Practical application dence over and may refer to the extensions (Beta). This of mixin-based inheritance is illustrated in a sketch of model shows that Beta and Smalltalk have inverted in- an extension to Modula-3. heritance hierarchies: a Smalltalk subclass refers to its parent using super just as a Beta prefix refers to its subpatterns using inner. 1 Introduction In the Object System (CLOS) and its predecessor, Flavors [13], multiple parent classes may A variety of inheritance mechanisms have been devel- be merged during inheritance. A class’s ancestor graph oped for object-oriented programming languages. These is linearized so that each ancestor occurs only once [7]. systems range from classical Smalltalk single inheri- With standard method combination for primary meth- tance [8], through the safer prefixing of Beta [12, 10], ods, the function call-next-method is used to invoke the to the complex and powerful com- next method in the inheritance chain. binations of CLOS [6, 9]. These languages have similar CLOS supports as a useful technique for build- object models, and also share the view that inheritance ing systems out of mixable attributes. A mixin is an is a mechanism for incremental programming. However, abstract subclass; i.e. a subclass definition that may they differ widely in the kind of incremental changes be applied to different superclasses to create a related supported. family of modified classes. For example, a mixin might In Smalltalk, subclasses can add additional methods be defined that adds a border to a window class; this or replace existing methods in the parent class. As a mixin could be applied to any kind of window to cre- result, there is no necessary relationship between the ate a bordered-window class. Semantically, mixins are behavior of instances of a class and the instances of its closely related to Beta prefixes. subclasses. The subclass methods can invoke any of the Linearization has been criticized for violating encap- original superclass methods via super. sulation, because it may change the parent-child re- In Beta, a subpattern (subclass) definition is viewed as lationships among classes in the inheritance hierarchy an extension of a previously defined prefix pattern. As [16, 17]. But the mixin technique in CLOS depends in Smalltalk, new methods may be defined. However, directly upon linearization and modification of parent- ∗Supported by grant CCR-8704778 from the National Science child relationships. Rather than avoid mixins because Foundation. they violate encapsulation, we argue that linearization Appeared in Proceedings of the ACM Conference on is an implementation technique for mixins that obscures Object-Oriented Programming: Systems, Languages, and their true nature as abstractions. Applications (OOPSLA) October 21- 25, 1990. By modest generalization of the inheritance models c 1990 ACM. Copied by permission. in Smalltalk and Beta, a form of inheritance based on

1 composition of mixins is derived. Mixin-based inheri- the Person display method using super display to display tance supports both the flexibility of Smalltalk and the the name, and then displays the degree. The net effect security of Beta. It also supports the direct encoding would be to print “A. Smith Ph..”. It would also be of CLOS multiple inheritance hierarchies without du- possible to prefix the name, as in the case of titles like plication of subclass definitions. However, since the hi- “Dr.”, by printing the title before calling super. erarchy is encoded as an explicit collection of linearized The subclass Graduate specifies only how Graduates inheritance chains rather than as a single inheritance differ from Persons [19]. This difference may be indi- graph, some changes to the hierarchy (especially if they cated explicitly as a delta, or set of changes. In this case might violate Snyder’s notion of encapsulation) cannot the set of changes is simply the new display method. easily be made. The original definition is also just a display method. Section 2 discusses the single-inheritance languages When combined, the new display method replaces the Smalltalk and Beta and shows that they support very original. different uses of a single underlying construct. Sec- To formalize this process, objects are represented as tion 3 analyzes multiple inheritance and linearization records whose fields contain methods [1, 15, 18, 3]. The in CLOS, with special focus on support for mixins. expression {a1 7→ v1, ··· , an 7→ vn} represents a record Section 4 presents a generalized inheritance mechanism with fields a1, . . . , an and associated values v1, . . . , vn. that supports the style of inheritance in Beta, Smalltalk, The expression .a represents selection of field a from and CLOS, with explicit support for mixins. In Sec- a record r. Record combination is a binary operator, tion 5 we sketch an extension to Modula-3 that illus- ⊕, that forms a new record with the fields from its two trates the use of generalized inheritance. Finally, Sec- arguments, where the value is from the left argument tion 6 summarizes our conclusions. in case the same field is present in both records. For example, {a 7→ 3, b 7→ ‘x’} ⊕ {a 7→ true, c 7→ 8} replaces the right value of a to produce {a 7→ 3, b 7→ ‘x’, c 7→ 8}. 2 Single Inheritance Languages To interpret super, it is necessary for the delta, or modifications, to access the original method inherited 2.1 Smalltalk Inheritance from Person. This is achieved by supplying the parent Inheritance in Smalltalk is a mechanism for incremental class methods as a parameter to the delta. The resulting derivation of classes. Smalltalk inheritance was adapted inheritance mechanism is an asymmetric combination of from [5, 14], and serves as the prototypical in- a parametric delta ∆ and a parent specification P : heritance mechanism. The primary subtlety in the pro- C = ∆(P ) ⊕ P. cess of inheritance is the interpretation of the special variables self and super. Self represents recursion, or This definition is a form of single inheritance: P refers self-reference, within the object instance being defined. to the inherited parent while ∆ is an explicit set of The interpretation of self has been addressed in previ- changes. The two occurrences of P do not indicate that ous work [3, 4, 15]; in this paper we focus on the in- it is instantiated twice, but that its information is used terpretation of super. Consider the following pair of in two contexts: for the interpretation of super and to Smalltalk classes. provide methods for the subclass. Suppressing the in- class Person terpretation of hidden instance variables, the example instance variables: name above has the following form. method: display P = {display 7→ name.display} name display ∆(s) = {display 7→ s.display, degree.display} ∆(P ) = {display 7→ name.display, degree.display} class Graduate superclass: Person Although deltas were introduced to make specifica- instance variables: degree tion of the inheritance mechanism more clear, deltas method: display are not independent elements of a Smalltalk program; super display. degree display they cannot stand on their own and are always part of a subclass definition, which has an explicit parent class. The class Person defines a name field and a method for In Smalltalk a subclass of Person may completely re- displaying the name. The subclass Graduate extends the place the display method with, for example, a routine display method to include the person’s academic degree. that displays the time of day. In Smalltalk inheritance, For example, a graduate with name “A. Smith” and the subclass is in control: there is no way to define degree “Ph.D.” would respond to the display method Person so that it forces subclasses to invoke its display by invoking the Graduate display method, which invokes method as part of their display operation.

2 2.2 Beta Inheritance resents any inner definitions supplied by subpatterns. For an instance of Person, the inner part of P 0 is bound Inheritance in Beta is designed to provide security from to the record of null methods: P 0(∅). replacement of a method by a completely different A subpattern specifies additional attributes which method. Inheritance is supported in Beta by prefixing of may also refer to any further inner behavior in later definitions. Beta employs a single definitional construct, subpatterns. If the attributes defined in the subpattern the pattern, to express types, classes and methods. As are specified by ∆0, then the result of prefixing by P 0 is this generality can be confusing, we use a simpler syn- the following composition: tax that distinguishes among the different roles1. The example given above is easily recoded in Beta: C0(inner) = P 0(∆0(inner) ⊕ inner) ⊕ ∆0(inner) Person: class 0 (# name : string; This means that the interpretation C of the subpat- display: virtual proc tern, when supplied an inner parameter, is the re- 0 (# do name.display; inner #); sult of combining the superpattern P specification 0 0 #); with the changes specified by ∆ . By applying P to ∆0(inner)⊕inner, the inner specification of P 0 is bound Graduate: class Person to the fields of the subpattern combined with any fur- (# degree: string; ther fields supplied by later subpatterns. The prefix methods take precedence over the suffix. In the exam- display: extended proc ple above, the equation for C0 is greatly simplified by (# do degree.display; inner #); examining the actual uses of inner: #); P 0(i) = {display 7→ name.display, i.display} The definition of Graduate is said to be prefixed by ∆0(i) = {display 7→ degree.display, i.display} Person. Person is the superpattern of Graduate, which, C0(i) = {display 7→ name.display, correspondingly, is a subpattern of Person. Display is degree.display, declared to be virtual, which means that it may be i.display } extended in a subpattern. This does not mean that it may be arbitrarily redefined, as in most object-oriented This formulation does not directly encode the restric- languages. tion that inner within a method m can refer only to the The behavior of the display method of a Person is to suffix method named m. In this sense inner is less gen- display the name and then perform the inner state- eral than Smalltalk’s super construct, but the restric- ment. For a plain Person instance, which has no inner tion is justified by the desire for security. An alterna- behavior, the inner statement is a null operation (i.e. tive formalization that captures this restriction involves skip or no-op). When a subpattern of Person is defined, representing each method as a function of its inner be- the inner statement will execute the corresponding dis- havior [3]. Prefixing is then defined as combination of play method in the subpattern. records such that duplicated fields are composed. Before The subpattern Graduate extends the behavior of the calling a method if must be applied to a null command Person display method by supplying inner behavior. For so that inner will have no effect. The resulting for- a Graduate instance G, the initial effect of G.display is malism is equivalent to the one given above, under the the same as for a Person: the original method from Per- condition that the fields of P 0 and ∆0 only access corre- son is executed. After the name is displayed, the inner sponding fields of inner. procedure supplied by Graduate is executed to display the graduate’s degree. The use of inner within Gradu- ate is again interpreted as a no-op. It only has an effect 2.3 Comparing Smalltalk and Beta if the display method is extended by a subpattern of The inheritance mechanisms of Smalltalk and Beta Graduate. It is impossible to arrange for printing a title, are different orientations of a common underlying like “Dr.”, before the name by inheriting Person; this mechanism. The underlying mechanism is a non- is because the choice to invoke inner after the name associative binary operator, £, that performs applica- has been built into the Person display method. In Beta tion of super/inner and combination of attributes. prefixing, the prefix controls the behavior of the result. The interpretation of the Person pattern is as a para- ∆ £ P = ∆(P ) ⊕ P metric definition of attributes, P 0. The parameter rep-

1This syntax is used by the implementors of Beta for tutorial The relationship between Beta and Smalltalk is demon- purposes [11]. strated by comparing the interpretations of inheritance

3 3 Multiple Inheritance and Mix- Smalltalk Beta ins User 3.1 CLOS Inheritance Parent ' $ ? ? CLOS supports a rich mechanism for multiple inheri- Prefix tance. Although there are several significant aspects of self var 6 CLOS inheritance, we focus only on standard method ¨ ¨ combination and primary methods. Here is the example $ % © © given above, recoded in CLOS. 6 inner ¨ (defclass Person () (name)) © Child (defmethod display ((self Person)) super ? (display (slot-value self ’name))) ¨ Suffix (defclass Graduate (Person) (degree)) self © var ¨ ? ¨ $ %(defmethod display ((self Graduate)) © © (call-next-method) 6 6 (display (slot-value self ’degree))) User & % The defclass construct includes the name of the new class, a list of its superclasses, and a list of its instance Figure 1: Inverse hierarchies in Smalltalk and Beta. variables. The argument list of the defmethod form de- fines the class on which the method is defined. Simple but effective method combination is supported by call- next-method, which plays the role of super in Smalltalk. in the two languages. The behavior of a subclass in- But like inner in Beta, call-next-method provides access stance can be compared concisely in this framework. only to the next method in the inheritance chain with the same message selector. C = ∆ £ P Smalltalk A CLOS class may inherit from more than one parent. As a result, a given ancestor may be inherited more than C0(∅) = P 0 £ ∆0(∅) Beta once. For example, the following classes result in Person being inherited twice by Research-Doctor. In these equations, ∆ represents the new explicit in- formation supplied by the subclass/subpattern, while (defclass Doctor (Person) ()) P represents the original attributes contributed by the (defmethod display ((self Doctor)) superclass/superpattern. The combination operator £ (display “Dr. ”) favors values from its left argument in case of a duplicate (call-next-method)) attribute. It is clear that the mechanism of inheritance is the (defclass Research-Doctor (Doctor Graduate) ()) same; only the direction of growth is different. In Smalltalk the new attributes are favored and may re- If care is not taken, the display method of Person will place inherited ones; in Beta the original attributes are be executed twice, and a Research-Doctor will display favored. Beta inheritance works in the opposite di- as “Dr. A. SmithA. Smith Ph.D.”. To remedy this sit- rection from inheritance in most object oriented lan- uation, CLOS linearizes the ancestor graph of a class guages, due to this role reversal between superpat- to produce an inheritance list in which each ancestor terns/subpatterns and subclasses/superclasses. Fig- occurs only once. The graph of ancestors of Research- ure 1 show this inversion by illustrating the semantic Doctor is linearized to Research-Doctor, Doctor, Grad- relationships in Smalltalk and Beta when a superclass uate, Person. This also solves the problem of method is placed above one of its subclasses. The figure includes invocation order, because ancestor classes are placed in the interpretation of self-reference, which is implicit in a linear order. Beta variable (var) references [3]. Neither direction of Each collection of method definitions may invoke inheritance is able to express the other, and each has its methods later in the linearized sequence via call-next- advantages and disadvantages. method. If the specification of parents P1,...,Pn is

4 given by ∆1,..., ∆n, then the interpretation C of the (defmethod display ((self Graduate-mixin)) subclass is defined by iteration of the inheritance oper- (call-next-method) ator over the list. (display (slot-value self ’degree))) C = ∆ £ (∆ £ (··· £ (∆ £ ∅))) 1 2 n This example illustrates a characteristic of mixins: Each specification in the list is applied to the result they invoke call-next-method even though they do not of the previous specification and combined with it. appear to have any parents. This would obviously lead The more complex method combination mechanisms of to an error if an instance of a mixin were created. Lin- CLOS can also be modeled in this framework. For ex- earization places the mixin into an inheritance chain be- ample, if before and after methods were distinguished fore other classes that support the method. This occurs then the base class, whose methods would be called af- in the new definition of Graduate: because Graduate- ter all other methods, could arrange for the last before mixin is listed before Person, the Person display method method to call the primary method, and the last pri- will be invoked by Graduate-mixin display. mary method to call the after method. (defclass Graduate (Graduate-mixin Person) ()) The process of linearization has been criticized for vi- olating encapsulation [17]. One argument is that the re- lationship between a class and its declared parents may In CLOS, mixins are simply a coding convention and be modified during linearization. This is demonstrated have no formal status. Although locally unbound uses by the example above, where in the linearization the of call-next-method are a clear indication that a class is class Graduate is placed between Doctor and Person, in a mixin, the concept has no formal definition, and any contradiction of the explicit declaration of Doctor that class could be used as a mixin if it contributes partial it inherits directly from Person. Only by being aware behavior. of the entire class hierarchy can the programmer foresee Using Graduate-mixin it is now possible to define dif- this. ferent kinds of classes that have “graduated” behavior. Using linearization, a CLOS multiple inheritance hi- In this example, the guard dog might have an obedience erarchy is reduced to a collection of inheritance chains, school degree. each of which can be interpreted using single inheri- (defclass Guard-Dog (Graduate-mixin Dog) ()) tance. However, a slight change to the original CLOS hierarchy may result in a very different collection of in- Neither Smalltalk nor Beta fully support mixins. In heritance chains. This is especially true if the changes Smalltalk, the effect of a mixin can be achieved by violate Snyder’s notion of encapsulation, as when a base explicitly creating subclasses and copying the mixin class is factored into two classes, because one of the new code into the subclass, preventing code-sharing and factors may interact with other classes during lineariza- abstraction. In Beta, an individual class closely re- tion. A less severe problem is that a given class may oc- sembles a mixin. However, it cannot be attached to cur in many chains, so if the collection was implemented independently-defined classes. Instead, the client class in a single-inheritance language, subclasses would have must be built with the mixin as a prefix. If a fam- to be duplicated. In order to eliminate this duplication, ily of mixed versions of a given class is needed, then the single-inheritance model must be generalized to al- the entire class must be copied for each prefixed mixin. low explicit naming and reuse of the deltas defined by Thus, in Smalltalk the mixin must be copied, while in subclasses. Beta the base class must be copied. This is consistent with our analysis of the direction of growth in Beta and 3.2 Mixin Programming Smalltalk. Mixin programming takes advantage of multiple in- In this section we discuss a common programming tech- heritance in a subtle and unintuitive way: mixins de- nique used in CLOS, called mixins. A mixin is an ab- pend upon linearization to place them in an appropri- stract subclass that may be used to specialize the be- ate location in the inheritance chain and to insert other havior of a variety of parent classes. It often does this classes between the mixin and its parents. When mix- by defining new methods that perform some actions and ins are viewed as abstract subclasses, or class definitions then call the corresponding parent methods. Mixins are parameterized by their parents, it is clear that lineariza- very similar to the deltas introduced informally in Sec- tion plays the role of application, by binding the mixin’s tion 2.1. For example, the notion of a graduate degree formal parent parameter to a specific class. This pro- as part of a name can be written as an independent cess of abstraction and application can be made more mixin. explicit by generalizing the inheritance mechanism com- (defclass Graduate-mixin () (degree)) mon to Smalltalk and Beta.

5 4 Inheritance as Composition of 5.2 Modula-3 Inheritance Mixins Modula-3 supports inheritance via object types. Object types are roughly analogous to classes in most object- Mixins are the basis for a compositional inheritance oriented languages. An example of object types in mechanism that generalizes Smalltalk and Beta, while Modula-3 is supporting the encoding of an encapsulated version of a CLOS multiple inheritance hierarchy. The basic idea type Person = of the generalization is to take mixins as the primary object name: string 2 definitional construct. Inheritance is then formulated methods display() := displayPerson as composition of mixins. New attributes may be com- end; posed in either the Smalltalk or Beta style (either over- writing or extending). Since mixins and composition type Graduate = Person are explicit, there is no need for implicit linearization: object degree: string a programmer would explicitly select the order of all methods display := displayGraduate mixin components. If a component is composed more end; than once it will appear as multiple copies in the re- sult; duplication is avoided by explicitly applying two procedure displayPerson(self: Person) = components to a shared parent. begin The mixin composition operator, ?, is the Beta inher- self.name.display(); itance operator, but is used in a slightly more general end displayPerson; form. Mixin composition takes two mixins as parame- ters, and returns a new mixin as a result. procedure displayGraduate(self: Graduate) = begin M1 ?M2 = fun(i) M1(M2(i) ⊕ i) ⊕ M2(i) Person.display(self); self.degree.display() In case of conflict, ? gives priority to the first param- end displayGraduate; eter. In M1, super/inner is bound during the inheri- tance operation to M . In M , super/inner is bound 2 2 In the example, Person defines an instance variable to the formal parameter i of the result. Assuming the name and a method display. The method is defined by basic attribute combination operator ⊕ is associative, ? providing a name, followed by a signature, or formal is associative. In addition, if ⊕ were commutative, then parameter list. In this case, the signature is empty. The ? would be commutative. method is then assigned a value, which is a separately Ordinary classes are viewed as degenerate mixins that defined procedure, displayPerson. If o is an object of type do not make use of their inner/super parameter. Mix- Person, o.display() is interpreted as displayPerson(o). ins thereby generalize Smalltalk classes, Beta patterns The definition of Graduate has two parts: A preex- and CLOS style mixins. Abstract classes are viewed as isting definition, Person, and a modification given by mixins that refer to fields not defined in self. A mixin is the object . . . methods . . . end clause. Graduate is a complete if it does not refer to its parent parameter, and subtype of Person, which is its supertype. Graduate in- defines all fields that it refers to in itself. Otherwise, it herits from Person, but includes a method override for is partial. Only complete mixins may be instantiated display. The method override names the method being meaningfully. overridden , and then assigns a new value to it, namely displayGraduate. A signature is not given, since it will 5 Application to an Existing always be identical to the signature of the correspond- ing method in the supertype. The overridden methods Language of Person may be referred to by Graduate through the syntax Person.methodname. This is similar to super in 5.1 Choice of Language Smalltalk, but more general. We have chosen Modula-3 [2] as a basis for an extension An object . . . methods . . . end clause corresponds incorporating mixin-based inheritance. Modula-3 is well to the notion of delta discussed above. As in Smalltalk, suited for such an extension, because it supports single deltas may not be defined independently of a parent. inheritance and is strongly typed. Single inheritance The following section presents an extension, whereby naturally generalizes to mixin-based inheritance. Strong such deltas become independent constructs. typing provides a framework in which mixins can be 2Modula-3 uses TEXT for character used safely and efficiently. strings. However, we will assume that string has been defined.

6 5.3 Extending Modula-3 a procedure that will work on any type, since it is de- fined on root, the root of the type hierarchy. Display- We extend Modula-3 by generalizing object types to GraduateMixin refers to the overridden display method mixins. A mixin may be an explicit modification, of through the pseudo-variable super, using the syntax su- the form object . . . methods . . . end. Alternately, a per.methodname. Procedures that reference super are mixin may be the result of combining two previously distinguished, using the keyword mixin procedure. defined mixins. In the code above, GraduateMixin plays a role similar to a subclass in Smalltalk. Reversing GraduateMixin’s Mixin = object . . . methods . . . end | position in the definition of Graduate reverses its role Mixin1 ? Mixin2 to that of a Beta subpattern. This is illustrated below, where PersonMixin functions as superpattern. The concrete syntax used in the examples below, dif- fers from the notation used until now in three respects. type PersonMixin = First, the order of the operands of the mixin operator object name: string is reversed, so that priority is given to the right hand methods display := displayPersonMixin operand. Second, the mixin operation is not written ex- super display() := No Op plicitly, but is implicit between each pair of mixins in end; a mixin definition. Finally, an optional super clause is added to modifications. The first two changes reflect ex- type Graduate = GraduateMixin PersonMixin; isting Modula-3 syntax, where a modification is written to the right of a base definition, with no composition op- mixin procedure erator in between. Adopting these changes helps make displayPersonMixin(self: PersonMixin) = the extension upwardly compatible. The third change begin is for typechecking purposes, as explained below. The self.name.display(); resulting syntax is super.display() end displayPersonMixin; Mixin0 = object . . . methods . . . end | object . . . methods . . . super . . . end | PersonMixin is in control, when combined with Gradu- 0 0 Mixin2 Mixin1. ateMixin. Graduate.display() invokes displayPersonMixin, where super.display() calls displayGraduateMixin. In The following is equivalent to the CLOS mixin exam- displayGraduateMixin super.display will use the default ple given above. value, No Op, corresponding to an empty inner clause type GraduateMixin = in Beta. object degree: string The examples above have an important advantage over their Smalltalk and Beta counterparts; all parts methods display := displayGraduateMixin of the definition can be reused, without being textually super display() := No Op copied. end; As a final example, we recode our earlier CLOS mul- tiple inheritance example: mixin procedure displayGraduateMixin(self: GraduateMixin) = type Doctor = begin object super.display() methods display := displayDoctor self.degree.display(); super display() := No Op end displayGraduateMixin; end;

procedure No Op(self: root) = begin end No Op; type ResearchDoctor = PersonMixin GraduateMixin Doctor; type Graduate = Person GraduateMixin; mixin procedure displayDoctor(self:Doctor) = Since GraduateMixin is defined independently of any begin parent, the signature of display cannot be inferred, and display(“Dr. ”); must be given in a special super clause. Similarly, dis- super.display() play’s overridden value is not known, but may be as- end displayDoctor; signed a default. In this case, the default value is No Op,

7 Note how the linear sequence of definitions is given would certainly differ in many details. However, the ba- explicitly, without reliance on linearization. sic strategy of generalizing object types (or classes, in other languages) to mixins is fundamental to any such 5.3.1 Typing extension. This section presents the typing rules for mixins in the Modula-3 extension. The typing of mixins has not been 6 Conclusion addressed in prior work, since mixins have not been in- troduced into a strongly typed language before. The inheritance mechanisms in the languages Beta, Type identity is defined as in Modula-3. Two types Smalltalk, and CLOS are representative of three differ- are identical iff their expanded definitions are identical. ent design choices for inheritance. Although the mech- The subtyping relation on mixins, T  S (read T is a anisms are, on the surface, very dissimilar, we identify subtype of S, or S is a supertype of T ) is defined as a common underlying structure. This underlying mech- follows: anism combines two sets of attributes such that dupli- cate attribute definitions are given a value from one set, 1. object . . . end  root. All mixins are subtypes where the value that is used may refer to the value being of root. eliminated. 2. If T1 = T2 T3 then T1  T2 and T1  T3, where Beta and Smalltalk both support single inheritance, the = sign denotes type identity. in which a single existing definition may be extended with new attributes. In Smalltalk the new attributes 3.  is reflexive and transitive. may replace existing attributes, which can be accessed For example ResearchDoctor  Doctor, as well as Re- directly via super. In contrast, Beta prohibits the ex- searchDoctor  GraduateMixin, ResearchDoctor  Per- tensions from replacing existing attributes; a new defini- sonMixin. What is less obvious is that if tion for an existing attribute has an effect only by being invoked when the original attribute executes the inner PGMixin = PersonMixin GraduateMixin; command. These two mechanisms have inverse rela- tionships between inherited definition and extensions: then ResearchDoctor  PGMixin. This follows from the Smalltalk subclass/superclass relationship is anal- the fact that ResearchDoctor = PGMixin Doctor by the ogous to the superpattern/subpattern relationship in definition of type identity. Recall that the mixin com- Beta, where super is analogous to inner. bination operator, ?, is associative. This is reflected in CLOS supports multiple inheritance, in which several the subtyping rules. existing definitions may be combined together. To avoid Additional rules for mixin composition include : duplication of components, CLOS linearizes the set of • A method should be mentioned in the super clause primitive components in the inherited definitions. This of a type, if it has been overridden. In practice, a linear list of components is then combined together by method override may be omitted from the super the same mechanism underlying Smalltalk and Beta: at- clause, if its signature can be inferred from context. tribute values appearing earlier in the list replace (and An example might be the definition of Graduate in may refer to) those appearing later. One disadvantage section 5.2. This exception is made for compatibil- of linearization is that the relationships between prim- ity with existing Modula-3 code. itive components may be changed. However, we show that linearization is the basis for the useful technique of • The pseudo-variable super may only be used in mixin programming. procedures declared as mixin procedures. The pro- We propose that the underlying inheritance mecha- cedure’s first parameter must be of a type that in- nism, which appears in two different restricted forms cludes a method override for every method refer- in Beta and Smalltalk, and is hidden behind lineariza- enced through super. tion in CLOS, be used as the foundation for a general inheritance construct. In this formulation, mixins be- • A mixin procedure can be invoked only as a come the basic definitional construct, and inheritance method. This guarantees that there is no way for is interpreted as mixin composition. Since the compo- the overridden methods of a mixin instance to be sition of mixins is explicit, the problem of linearization accessed from outside the instance. violating encapsulation does not arise. All rules given in this section can be statically en- It does not appear difficult to extend Beta and forced. This is a necessary condition for safety, and Smalltalk to support mixins and generalized inheri- for an efficient implementation. These rules are spe- tance. This work could be applied to CLOS, which al- cific to Modula-3, and an extension of another language ready supports mixins, to make them more explicit and

8 less susceptible to encapsulation problems. A sketch of [12] Kristensen, B. B., Madsen, O. L., Moller- an extension to Modula-3 illustrates a possible design Pendersen, B., and Nygaard, K. Abstraction for mixins and generalized inheritance. mechanisms in the Beta . Information and Control (1983). References [13] Moon, D. A. Object-oriented programming with Flavors. In Proc. of ACM Conf. on Object-Oriented [1] Cardelli, L. A semantics of multiple inheritance. Programming, Systems, Languages and Applica- In Semantics of Data Types (1984), vol. 173 of Lec- tions (1986), pp. 1–8. ture Notes in Computer Science, Springer-Verlag, pp. 51–68. [14] Papazoglou, M. P., Georgiadis, P. I., and Maritsas, D. G. An outline of the programming [2] Cardelli, L., Donahue, J., Glassman, L., language Simula. Computer Language 9, 2 (1984), Jordan, M., Kalsow, B., and Nelson, G. 107–131. Modula-3 report (revised). Tech. Rep. 52, Digital Equipment Corporation Systems Research Center, [15] Reddy, U. S. Objects as closures: Abstract Dec. 1989. semantics of object-oriented languages. In Proc. ACM Conf. on Lisp and Functional Programming [3] Cook, W. A Denotational Semantics of Inheri- (1988), pp. 289–297. tance. PhD thesis, Brown University, 1989. [16] Snyder, A. Encapsulation and inheritance [4] Cook, W., and Palsberg, J. A denota- in object-oriented programming languages. In tional semantics of inheritance and its correctness. Proc. of ACM Conf. on Object-Oriented Pro- In Proc. of ACM Conf. on Object-Oriented Pro- gramming, Systems, Languages and Applications gramming, Systems, Languages and Applications (1986), pp. 38–45. (1989), pp. 433–444. [17] Inheritance and the development of [5] Dahl, O.-J., Myhrhaug, B., and Nygaard, Snyder, A. encapsulated software systems. In Research Direc- K. The SIMULA 67 common base language. Tech. rep., Norwegian Computing Center, Oslo, Norway, tions in Object-Oriented Programming. MIT Press, 1970. Publication S-22. 1987, pp. 165–188. [6] DeMichiel, L., and Gabriel, R. The Com- [18] Wand, M. Type inference for record concatenation mon Lisp Object System: An overview. In Euro- and multiple inheritance. In Proc. IEEE Sympo- pean Conference on Object-Oriented Programming sium on Logic in Computer Science (1989), pp. 92– (June 1987), pp. 151–170. 97. [7] Ducournau, R., and Habib, M. On some algo- [19] Wegner, P., and Zdonik, S. B. Inheritance as a rithms for multiple inheritance in object-oriented mechanism for incremental modification. In Euro- programming. In European Conference on Object- pean Conference on Object-Oriented Programming Oriented Programming (1987), pp. 243–252. (1988), pp. 55–77. [8] Goldberg, A., and Robson, D. Smalltalk-80: the Language and Its Implementation. Addison- Wesley, 1983. [9] Keene, S. E. Object-Oriented Programming in Common Lisp. Addison-Wesley, 1989. [10] Kristensen, B. B., Madsen, O. L., Moller- Pedersen, B., and Nygaard, K. The Beta programming language. In Research Directions in Object-Oriented Programming. MIT Press, 1987, pp. 7–48. [11] Kristensen, B. B., Madsen, O. L., Moller- Pederson, B., and Nygaard, K. The Beta pro- gramming language – a Scandinavian approach to object-oriented programming, Oct. 1989. OOPSLA Tutorial Notes.

9