From sce!mitel!uunet!snorkelwacker!tut.cis.ohio-state.edu!ucbvax!hplabs!hpfcso!hpfcbig!tim Fri Feb 16 07:18:45 EST 1990 Article: 74 of comp.lang.lisp.x Path: cognos!sce!mitel!uunet!snorkelwacker!tut.cis.ohio-state.edu!ucbvax!hplabs!hpfcso!hpfcbig!tim From: tim@hpfcbig.SDE.HP.COM (Tim Mikkelsen) Newsgroups: comp.lang.lisp.x Subject: Re: intro to XLISP objects Message-ID: <1170005@hpfcbig.SDE.HP.COM> Date: 12 Feb 90 16:23:48 GMT References: <1170004@hpfcbig.SDE.HP.COM> Organization: HP SESD, Fort Collins, CO Lines: 434 XLISP 2.0 OBJECTS PRIMER by Tim I Mikkelsen February 3, 1990 Copyright (c) 1990 by Tim I. Mikkelsen. All Rights Reserved. No part of this document may be copied, reproduced or translated for commercial use without prior written consent of the author. Permission is granted for non-commercial use as long as this notice is left intact. ________________________________________________________________ One of the features in the design of XLISP is object-oriented programming. This primer is intended to serve as a very brief introduction to the object facilities of the XLISP 2.0 dialect of LISP. Note that the object features of XLISP are not based on other existing object definitions in other LISP dialects. If you find problems in the primer, I'd appreciate hearing. Tim Mikkelsen 4316 Picadilly Drive Fort Collins, Colorado 80526 PROGRAMMING STYLES ______________________________________________________________________________ There are many programming paradigms (models). Some of the paradigms are procedural, functional, rule-based, declarative and object-oriented. A language can have aspects of one or many of these programming models. Procedure-Oriented The programming paradigm most people are familiar with is the procedural style. The primitives in procedural programming are: subroutines and data structures. Through these primitives, programmers have some limited abilities to share programs and program fragments. C and Pascal are examples of procedural languages. Some procedural languages (such as Modula and ADA) have extensions that provide for better sharing of code. Object-Oriented Programming Object-oriented programming is based on the primitives of objects, classes and messages. Objects are defined in terms of classes. Actions occur by sending a message to an object. An object's definition can be inherited from more general classes. Objective-C and C++ both are object-oriented dialects of the C language. Many dialects of LISP have some object oriented extension (Flavors, Common LOOPS, CLOS and others). There currently is standards work proceeding to add object-oriented programming to Common LISP. Object Oriented Programming So, the object-oriented programming model is based around the concepts of objects, classes and messages. An object is essentially a black box that contains internal state information. You send an object a message which causes the object to perform some operation. Objects are defined and described through classes. One aspect of an object is that you do not have to know what is inside - or how it works - to be able to use it. From a programming point of view, this is very handy. You can develop a series of objects for someone to use. If you need to change what goes on inside, the users of the objects should be unaware. Another aspect of objects is that of inheritance. You can build up new classes from existing classes by inheriting the existing class's functionality and then extending the new definition. For example, you can define a tool class (with various attributes) and then go about creating object instances tool-1, tool-2, and so on. You can also create new sub-classes of the tool class like power-tool. This is also very handy because you don't have to re-implement something if you can build it up from existing code. XLISP OBJECT-ORIENTED PROGRAMMING ______________________________________________________________________________ XLISP OBJECT TERMINOLOGY There are, as previously mentioned, many different languages with object-oriented extensions and facilities. The terminology, operations and styles of these are very different. Some of the main definitions for XLISP's object-oriented extensions are: Object data type The OBJECT DATA TYPE is a built-in data type of XLISP. Members of the object data type are object instances and classes. Object instances An OBJECT INSTANCE is a composite structure that contains internal state information, methods (the code which respond to messages), a pointer to the object instance's defining class and a pointer to the object's super-class. XLISP contains no built-in object instances. Class objects A CLASS OBJECT is, essentially, the template for defining the derived object instances. A class object, although used differently from a simple object instance, is structurally a member of the object data type. It is also contains the linking mechanism that allows you to build class hierarchies (sub-classes and super-classes). XLISP contains two built-in class objects: OBJECT and CLASS. Message selector The MESSAGE SELECTOR is the symbol that is used to select a particular action (Method) from the object. Message The MESSAGE is the combination of the message selector and the data (if any) to be sent to the object. Method The METHOD is the actual code that gets executed when the object receives the Message. SENDING MESSAGES The mechanism for sending messages to XLISP objects is via the SEND function. It takes an object, a message selector and various optional arguments (depending on the message selector). The way that a user creates a new object is to send a :NEW message to a previously defined class. The result of this SEND will return an object, so this is normally preceded by a SETQ. The values shown in the examples that follow may not match what you see if you try this on your version of XLISP - this is not an error. The screens that are used in the various examples are similar to what you should see on your computer screen. The ">" is the normal XLISP prompt (the characters that follow the prompt is what you should type in to try these examples). ________________________________________________________________ | | > (setq my-object (send object :new)) | # |________________________________________________________________ The object created here is of limited value. Most often, you create a class object and then you create instances of that class. So in the following example, a class called MY-CLASS is created that inherits its definition from the a built-in CLASS definition. Then two instances are created of the new class. ________________________________________________________________ | | > (setq my-class (send class :new '())) | # | | > (setq my-instance (send my-class :new)) | # | | > (setq another-instance (send my-class :new)) |# |________________________________________________________________ CLASSES Previously, a :NEW message was used to create an object. The message used to see what is in an object is the :SHOW message. ________________________________________________________________ | | > (send my-class :show) | Object is #, Class is # | MESSAGES = NIL | IVARS = NIL | CVARS = NIL | CVALS = NIL | SUPERCLASS = # | IVARCNT = 0 | IVARTOTAL = 0 | # |________________________________________________________________ From the display of the MY-CLASS object you can see there are a variety of components. The components of a class are: Class Pointer This pointer shows to what class the object (instance or class) belongs. For a class, this always points to the built-in object CLASS. This is also true of the CLASS object, its class pointer points to itself. Superclass Pointer This pointer shows what the next class up the class hierarchy is. If the user does not specify what class is the superclass, it will point to the built-in class OBJECT. Messages This component shows what messages are allowed for the class, and the description of the method that will be used. If the method is system-defined, it will show up in the form of '#'. Remember that the class hierarchy (through the Superclass Pointer) is searched if the requested message is not found in the class. Instance Variables This component lists what instance variables will be created when an object instance is created. If no instances of the class exist, there are no Instance Variables. If there are 5 instances of a class, there are 5 complete and different groups of the Instance Variables. Class Variables The CLASS VARIABLES (CVAR) component and Values lists what class variables exist within the class. The Class Values (CVAL) component shows what the current values of the variables are. Class Variables are used to hold state information about a class. There will be |Bone of each|A of the Class Variables, independent of the number of instances of the class created. A BETTER EXAMPLE The example previously shown does work, but the class and instances created don't really do anything of interest. The following example sets up a tool class and creates some tool instances. ________________________________________________________________ | | > (setq my-tools (send class :new '(power moveable operation))) | # | | > (send my-tools :answer :isnew '(pow mov op) | '((setq power pow) | (setq moveable mov) | (setq operation op))) | # | | > (setq drill (send my-tools :new 'AC t 'holes)) | # | | > (setq hand-saw (send my-tools :new 'none t 'cuts)) | # | | > (setq table-saw (send my-tools :new 'AC nil 'cuts)) | # |________________________________________________________________ So, a class of objects called MY-TOOLS was created. Note that the class object MY-TOOLS was created by sending the :NEW message to the built-in CLASS object. Within the MY-TOOL class, there are three instances called DRILL, HAND-SAW and TABLE-SAW. These were created by sending the :NEW message to the MY-TOOLS class object. Notice that the parameters followed the message selector. INSTANCES The following is a display of the contents of some of the previously created instances: ________________________________________________________________ | | > (send drill :show) | Object is #, Class is # | POWER = AC | MOVEABLE = T | OPERATION = HOLES | # | | > (send hand-saw :show) | Object is #, Class is # | POWER = NONE | MOVEABLE = T | OPERATION = CUTS | # |________________________________________________________________ From the display of these instances you can see there are some components and values. The components of an instance are: Class Pointer This pointer shows to which class the current object instance belongs. It is through this link that the system finds the methods to execute for the received messages. Instance Variables The Instance Variables (IVAR) component and Values lists what variables exist within the instance. The Instance Values component holds what the current values of the variables are. Instance Variables are used to hold state information for each instance. There will be a group of Instance Variables for each instance. METHODS There have been a few of the messages and methods in XLISP shown to this point (:NEW and :SHOW). The following are the methods built into XLISP: :ANSWER The :ANSWER method allows you to define or change methods within a class. :CLASS The :CLASS method returns the class of an object. :ISNEW The :ISNEW method causes an instance to run its initialization code. When the :ISNEW method is run on a class, it resets the class state. This allows you to re-define instance variables, class variables, etc. :NEW The :NEW method allows you to create an instance when the :NEW message is sent to a user-defined class. The :NEW method allows you to create a new class (when the :NEW message is sent to the built-in CLASS). :SHOW The :SHOW method displays the instance or class. SENDING MESSAGES TO A SUPERCLASS In addition to the SEND function, there is another function called SEND-SUPER. The SEND-SUPER function causes the specified message to be performed by the superclass method. This is a mechanism to allow chaining of methods in a class hierarchy. This chaining behavior can be achieved by creating a method for a class with the :ANSWER message. Within the body of the method, you include a SEND-SUPER form. This function is allowed only inside the execution of a method of an object. OBJECT AND CLASS The definition of the built-in class OBJECT is: ________________________________________________________________ | | > (send object :show) | Object is #, Class is # | MESSAGES = ((:SHOW . #) | (:CLASS . #) | (:ISNEW . #)) | IVARS = NIL | CVARS = NIL | CVALS = NIL | SUPERCLASS = NIL | IVARCNT = 0 | IVARTOTAL = 0 | # |________________________________________________________________ Note that OBJECT is a class - as opposed to an "instance-style" object. OBJECT has no superclass, it is the top or root of the class hierarchy. OBJECT's class is CLASS. ________________________________________________________________ | | > (send class :show) | Object is #, Class is # | MESSAGES = ((:ANSWER . #) | (:ISNEW . #) | (:NEW . #)) | IVARS = (MESSAGES IVARS CVARS CVALS SUPERCLASS | IVARCNT IVARTOTAL) | CVARS = NIL | CVALS = NIL | SUPERCLASS = # | IVARCNT = 7 | IVARTOTAL = 7 | # |________________________________________________________________ CLASS has a superclass of OBJECT. It's class is itself - CLASS.