Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!zephyr.ens.tek.com!tekcrl!brucec From: brucec@phoebus.phoebus.labs.tek.com (Bruce Cohen;;50-662;LP=A;) Newsgroups: comp.object Subject: prototypes and degenerate cases Message-ID: Date: 11 Sep 90 21:14:57 GMT Sender: news@tekcrl.LABS.TEK.COM Organization: Tektronix Inc. Lines: 69 I've just been reading the Self papers, and it occurred to me that using prototypes for inheritance could solve a problem which has been annoying me for quite some time. Maybe some of you out there coould comment on the theory and/or practice of the idea. Consider an object-oriented graphic drawing system, in which there's a general shape object, a polygon object, a rectangle object, a circle object, and an ellipse object. One way you could arrange class inheritance for such objects is like this: Shape | ------------ | | Polygon Ellipse | | Rectangle Circle That is, the root class is an abstract shape class, and it's subclasses are the most general concrete classes, with more specific (i.e., degenerate case) classes inheriting from them. Well that's fine from a static viewpoint, but consider that one reason to build a system like this is that it may be (and usually is) cheaper both to draw and to store a rectangle than a general polygon, and a circle than an ellipse. OK, so we can create rectangles when we know that a polygon has 4 sides, or circles when we know that the foci of an ellipse are coincident. But what happens when objects can change over time? How do we dynamically mutate a rectangle to a polygon and back again while retaining the cost savings of the more refined object? In a class-based system, either you use a message like become: otherObject in Smalltalk, which is really a system utility, and implies that there is a global object table or some other centralized means of insuring that references to the old object get update, or you have to have creation/conversion methods for objects which can be called when a mutator method discovers a degeneracy (this is the technique you would have to use in C++). The mutator would create (e.g.) a new degenerate object, copy the relevant part of the state of the non-degenerate one, then install the new one in the right place and manually update references to the old object. Suppose instead that the objects inherited from prototypes, and the mutator merely changed the appropriate parent pointers to (e.g.) remove a degenerate object's redundant slots and change it's behavior to the less costly method. Consider the ellipse being converted to a circle (warning: Self notation): Ellipse Circle: ------ ------- parent:-----------> traits circle parent:-----------> traits ellipse focus1 -----------> 0@0 <------------ center focus2 -----------> 0@0 focus1: <- focus2: <- focus2: <- major radius -----> 1 <------------ radius minor radius -----> 1 major radius: <- minor radius: <- This seems significantly cleaner than becomes, and perhaps less work than the hand-crafted mutator in the class-based approach. Anyone have any comments? -- --------------------------------------------------------------------------- NOTE: USE THIS ADDRESS TO REPLY, REPLY-TO IN HEADER MAY BE BROKEN! Bruce Cohen, Computer Research Lab email: brucec@tekcrl.labs.tek.com Tektronix Laboratories, Tektronix, Inc. phone: (503)627-5241 M/S 50-662, P.O. Box 500, Beaverton, OR 97077