Object-Oriented Programming with Flavors
Total Page:16
File Type:pdf, Size:1020Kb
Object-Oriented Programming with Flavors David A. Moon Symbelics, Inc. programs. This newly-designed Flavors is the version Abstract described in this paper. It will be released with the next Symholics software release. (5) This paper describes Symbolics' newly redesigned object- oriented programming system, Flavors. Ravors encourages What is obJect-orlentod programm/ng? program modularity, eases the development of large, complex programs, and provides high efficiency at run We view object-oriented programming as a techn/que for time. Flavors is integrated into Lisp and the Symbelics organizing very large programs. This technique makes it program development environment. This paper describes practical to deal with programs that would otherwise be the philosophy and soma of the msjor characteristics of impossibly complex. Symbollcs' Flavors and shows how the above goals are addressed. Full details of Flavors are left to the An object-oriented program consists of a set of objects and programmers' manual, Re, fence Guile to 8ymboli~ a set of operations on those objects. These entities are Common Lisp. (5) not de/'med in a monolithic way. Instead, the dei'mitions of the operations are distributed among the various objects that they can operate upon. At the same time, History of F/avora the definitions of the objects are distributed among the The origulal Flavors system was developed by the /,fiT various facets of their behavior. An object-oriented Lisp Machine group in 1979. (I, 2, 3) It was used to build programming system is an organizations] framework for a window system and later applied to other system combining these distributed definitions and managing the programming. In 1981, Symbel/cs designed a more interactions among them. efficient implementation of Flavo~ Since that time, we Object-oriented programming is also an abstract/on have made increasingly heavy use of Flavors in nearly mechanism. A program that manipulates an object uses every aspect of the Symbelics 3600 software, such as I/O certain defined operations to manipulate it. These streams, network control programs, the debugger, the operations serve as an interface, and the program does editor, and user interface facilities. Flavors permeate not need to know how the object implements the beth the operating system and higher-level utilities. The operations. The implementation of one operation can be same Flavors tools used in-house are fully documented and different for different kinds of objects. At the same time, are used by most SymbeLics customers to build their an object's behavior can be divided into several facets, application programs. which need not know each other's internal detaiLs. Five years' experience with Flavors has pointed out the strengths and weaknesses of the original design. In 1985 Goals of Flavors we undertook a thorough redesign of Flavors to solve the problems that we had identified. The result is a new There are many possible and useful styles of object- Flavo~ system that has been implemented at Symbelics oriented programming. Flavors adopts an approach aimed and has been used in-houas to develop several complex at these goals: * Encourage program modularity. By this we mean that Flavors should make it easier to construct programs out of existing parts, to modify the behavior of Permission to copy without fee all or pen of this material is granted provided that the copies are not made or distributed for direct commercial advantage. existing programs without massively rewriting them, the ACM copyright notice and the title of the publication and its date appear, to understand programs one piece at a time, and to and notice is given that copyingis by permission of the Association for identify interfaces between modules. Computin$ Machinery. To copy otherwise, or to republish, requires a fee and/ or specificpermission. • Ease development of large, complex programs. In addition to encouraging modularity, Ravors should © 1986 ACM 0-89791-204-7/86/0900-0001 75¢ September 1986 OOPSLA '86 Proceedings 1 allow programs to be constructed incrementally, make it possible to change data representations and program --> 14 organization while the program is running, and provide tools for analyzing programs. Similarly, the :writ able- inst ance-veriable s option allows us to alter the value of an instance • Provide high efficiency at run-time. The CPU time and variable: page fault rate associated with object-oriented operations should not be very much larger than that (setf (ship-mass my-ship) i00) associated with ordinary function calling and data --> 100 manipulation. This must be accomplished without compromising other goals. Generic functions The operations that are performed on objects are . Be compatible with the previous Flavors system. By this known as generic functions. we mean tools and backward-compatibility features to ease conversion of programs written with the old Methods Flavors to run with the new Flavors. Compatibility The Lisp function that performs a generic function on features are not discussed in this paper. instances of a certain flavor is called a method. The instance variables are accessible by name inside the Later sections discuss how these goals are met. We first body of a method. Often, one generic function has present the concepts of Flavors. several methods defined for it, attached to different flavors. An example method: Basic Flavors Concepts (defmethod (ship-speed ship) () It is often convenient to organize programs around objects, (sqrt (+ (expt x-velocity 2) which model real-world things. Each real-world object is (expt y-velocity 2)))) modelled by a single Lisp object. Each object has some state and a set of operations that can be performed on it. Generic Functions A Flavors program is built around: A generic function operates on an object by selecting one Flavors or more methods that implement the generic operation in Each kind of object is implemented as a flavor. A a specialized way for that object. One of the arguments flavor is an abstraction of the characteristics that all (usually the first) to a generic function is the object: the objects of this flavor have in common. It is a new available methods are those attached to its flavor. Generic aggregate data type. For example, this form defines a functions are the interface between objects. They provide flavor that represents ships: abstraction and isolation between modules. (defflavor ship Figure I shows the differences between ordinary Lisp (x-velocity y-velocity mass) functions and generic functions. () : readable-instance-variables :writ able-instance-variables Ordinary Func~ons Gener/~ Func~ons : init able-inst ance-variables) Have a single Have a distributed definition. Instances of a flavor definition. Each object is implemented as an instance of a flavor. Interface is specified Interface can be specified For example, here we create and initialize an instance by defun. by defgenerlc or defmethod. of the ship flavor: Do not treat flavor First argument is usually (setq my-ship instances specially. an instance of a flavor. (make-instance 'ship :mass 14 :x-velocity 24 Implementation is the Implementation varies £rom :y-velocity 2) ) same whenever the ceil to call, depending on function is called. the flavor of the first Instance variables argument. This is a set of named variables with separate values Figure I for each instance. The values of the instance Differences between ordinary and generic Lisp functions. variables represent the state of each object. The instance variables of the chip flavor are x-velocity, ........................................................ y-velocity, and mass. The :readable-lnstance- variables option generates accessor functions for Generic functions are smoothly integrated into the Lisp reading the values of instance variables; for example: environment. Ordinary functions and generic functions are called with the same syntax. Making generic functions (ship-mass my-ship) syntactically and semantically compatible with ordinary functions has the following advantages: 2 OOPSLA '86 Proceedings September 1986 • The caller of a function need not know whether it is The goal of ordering flavor components is to preserve the generic. modularity of programs. A favor should be treated as an intact unit, with well-defined characteristics and behavior; • The Common Lisp package system (4) can be used to it is essential that mixing flavors together does not alter isolate modules and to distinguish between public and the internal details of any of the component flavors. This private interfaces by exporting the names of public makes it easier to assemble a program from pieces by generic functions. combining pre-existing flavors. The rules for ordering • Debugging tools such as trace can be used on generic components support this by ensuring that a flavor's components will be in the same order when that flavor is functions. part of another as they are when it stands alone. • Program-development tools that get the argument list or documentation of a function work equally well on Here is an example of ordering components. The third subform of d~fflavor is the list of direct components. generic functions. defflavor pie () (apple cinnamon)) Mixing Flavors defflavor apple () (fruit)) defflavor cinnamon () (spice)) A typical flavor is defu~d by combining several other defflavor fruit () (food)) flavors, called its components. The new flavor inherits defflavor spice () (food)) instance variables, methods, and additional component defflavor food