Modular Object-Oriented Programming with Units and Mixins
Total Page:16
File Type:pdf, Size:1020Kb
Mo dular Ob ject-Oriented Programming with Units and Mixins Rob ert Bruce Findler Matthew Flatt Department of Computer Science Rice University Houston, Texas 77005-1892 class languages follow from a single language design prin- Abstract ciple: specify connectionsbetween modules or classes sepa- Mo dule and class systems haveevolved to meet the demand rately from their de nitions. for reuseable software comp onents. Considerable e ort has The shared principle of separating connections from def- b een invested in developing new mo dule and class systems, initions makes units and mixins synergistic. When units and in demonstrating howeach promotes co de reuse. How- and mixins are combined, a programmer can exploit the en- ever, relatively little has b een said ab out the interaction of capsulation and linking prop erties of units to control the these constructs, and how using mo dules and classes together application of mixin extensions (e.g.,tochange the class can improve programs. In this pap er, we demonstrate the extended by a particular mixin). synergy of a particular form of mo dules and classes|called In Section 5, we motivate in more detail the design b e- units and mixins, resp ectively|for solving complex reuse hind MzScheme's units and mixins, but their synergy is b est problems in a natural manner. demonstrated with an example. The bulk of this pap er therefore presents an in-depth example, showing how the synergy of units and mixins solves an old extensibility prob- 1 Intro duction lem [7, 40] in a natural manner. Section 2 describ es the extensibili ty problem, and Section 3 develops a rough solu- Mo dule and class systems b oth promote co de reuse. In the- tion the problem using conventional classes. Section 4 intro- ory,many uses of classes can b e simulated with mo dules, duces units and mixins to re ne and complete the solution. and viceversa. Exp erience shows, however, that program- Sections 5 and 6 extract lessons from the example for the mers need b oth constructs b ecause they serve di erentpur- design of mo dular ob ject-oriented programming languages. p oses [43]. A mo dule delineates b oundaries for separate de- Finally, Section 7 relates our work to other research. velopment. A class p ermits ne-grained reuse via selective inheritance and overriding. Since mo dules and classes aid di erent patterns of reuse, 2 The Extensibility Problem mo dern languages provide separate constructs for each. Un- fortunately, the reuse allowed byconventional mo dule and The following table summarizes the extensibili ty problem: class systems is limited. In these systems, mo dules and original variants extension classes are hard-wired to a sp eci c context, i.e., to sp eci c z }| { z }| { mo dules or to a sp eci c sup erclass. 2 ; In previous work, we separately describ ed the novel mo d- ( ule and class systems in MzScheme [12]. MzScheme's mo d- original draw draw( 2 ) draw( ) draw( ; ) ules [13], called units , are roughly likeJava packages, ex- op erations cept that units are linked through an external linking sp ec- shrink shrink( 2 ) shrink ( ) shrink ( ; ) n i cation, instead of through a xed internal sp eci cation. extension rotate rotate( 2 ) rotate ( ) rotate ( ; ) MzScheme's ob ject language [14] provides mixins , whichare likeJava classes except that a mixin is parameterized over its sup erclass, so it can b e applied multiple times to create The p ortion of the table contained in the dotted b ox repre- di erent derived classes from di erent base classes. The ad- sents a program comp onentthatprovides several op erations, vantages of units and mixins over conventional mo dule and draw and shrink, on a collection of data, geometric shap es like squares and circles. A programmer may wish to use This researchwas partially supp orted by a Lo dieska Sto ckbridge such a comp onent in three di erentcontexts: Vaughan Fellowship, NSF grants CCR-9619756, CDA-9713032,and CCR-9708957, and a Texas ATP grant. 1. The programmer may wish to include the comp onent as is. 2. The programmer may wish to extend the datatyp e with a variant, rep ositioned shap es, and adapt the col- lection of op erations accordingly. 3. The programmer may wish to add a new op eration, To app ear: ICFP { Sept. 27-29 1998, Baltimore, MD rotate. 1 ? ? ? ? ? ? ? ? ? ? ? Client Client Client Client Client (a) Original Datatyp e (b) New Variant (c) New Op eration Figure 1: Extensible programming on datatyp es Toavoid duplicate maintenance, or b ecause the comp onent 3 Extensible Programming with Classes is acquired in ob ject form, the comp onentmust b e organized Figure 1 outlines our solution to the extensibili ty problem: so that programmers can add b oth new forms of data and new op erations without modifying or recompiling Diagram (a) represents the original comp onent. The rhombus stands for the datatyp e, and the rectangles the original program comp onent, or denote the datatyp e's variants. The oval is a clientof its existing clients. the datatyp e comp onent. Such a program organization dramatically increases the p o- Diagram (b) shows the datatyp e extended with a new tential for software reuse and enables the smo oth integration variant. The extension is contained in the right inner of proprietary mo dules. dashed b ox. The solid b ox on the left represents the Neither standard functional nor ob ject-oriented strate- unmo di ed datatyp e co de from (a). The original client gies o er a satisfactory way to implement the comp onent is also preserved, and a new client of the datatyp e and its clients. In a functional language, the variants can b e exploits the variant extension. implemented as a typ e, with the op erations as functions on Diagram (c) shows extension in the other direction: the typ e. Using this approach, the set of op erations is easily adding a new op eration to the datatyp e. As b efore, extended, but adding a new variant requires mo difying the the extension is implemented by the inner dashed b ox functions. In an ob ject-oriented language, the variants can while the solid b ox represents the unmo di ed existing b e implemented as a collection of classes, with the op era- implementation from (b). The new squares in the ex- tions as metho ds common to all of the classes. Using this tension represent the implementation of the op eration approach, the datatyp e is easily extended with a new vari- for eachvariant. The existing clients have not b een ant, but adding a new op eration is typically implemented mo di ed, although they now refer to the extended vari- by mo difying the classes. ants. The existing literature provides three solutions to the problem. Kuhne's [24] solution, which relies on generic pro- The remainder of this section develops a concrete example, cedures with double-dispa tchin g, can interfere with the hi- an evolving shap e program [11, 23]. Since Figure 1 can b e erarchical structure of the program. Palsb erg and Jay's [32] approximated using conventional classes, we rst use only solution is based on re ection op erators and incurs a sub- language features available in a typical ob ject-oriented lan- stantial run-time p enalty. Krishnamurthi, Felleisen, and guage. But, classes are not enough; Section 4 intro duces Friedman [11, 23] prop ose an ecient solution that works units and mixins to complete the solution. with standard class mechanisms, but it requires the imple- mentation (and maintenance) of a complex programming 3.1 Shap e Datatyp e proto col. All of these solutions are partial b ecause they do not address the reuse of clients. In contrast, the combination Initially, our shap e datatyp e consists of three variants and of units and mixins solves the problem simply and elegantly, one op eration: rectangles, circles, and translated shap es for and it addresses the reuse of b oth the original comp onent drawing. The rectangle and circle variants contain numb ers and its clients. that describ e the dimensions of the shap e. The translated variant consists of twonumbers, and , and another x y 2 (define Shape (interface () draw)) (define BB-Shape (interface (Shape) bounding-box)) (define Rectangle (define BB-Rectangle (class* null (Shape)(width height) (class* Rectangle (BB-Shape)(width height) (public (public [draw (lambda (window x y) :: :)]))) [bounding-box (lambda () (make-object BB 0 0 width height))]) (define Circle (sequence (super-init width height)))) (class* null (Shape)(radius) (public (define BB-Circle [draw (lambda (window x y) :: :))])) (class* Circle (BB-Shape)(radius) (public (define Translated [bounding-box (class* null (Shape)(shape ) (lambda () (make-object BB (- radius)(- radius) x y (public radius radius))]) [draw (lambda (window x y) (sequence (super-init r)))) (send shape draw window (+ x )(+y )))]))) (define BB-Translated x y (class* Translated (BB-Shape)(shape ) x y (public Figure 2: Shap e classes [bounding-box (lambda () :::)]) (sequence (super-init shape )))) x y (define BB-Union (define display-shape (class* Union (BB-Shape)(left right) (lambda (shape) (public (if (not (is-a? shape Shape)) [bounding-box (lambda () :::)]) (error \expected a Shape")) (sequence (super-init left right)))) (let ([window :::]) (send shape draw window 00)))) (define BB (class* null () (left top right bottom) (display-shape (make-object Translated :::)) (make-object Rectangle 50 100) 30 30)) (define display-shape (lambda (shape) Figure 3: Two shap e clients (if (not (is-a? shape BB-Shape)) (error \expected a BB-Shape")) (let*([bb (send shape bounding-box)] [window :::][x :::][y :::]) shap e.