Previous | Table of Contents | Next |
Note that make-instance for square now takes new initargs. This interface cant be preserved. The convention is to define a constructor function that must be redefined to call make-instance with the new arguments, as in
(defun make-square (lower-left upper-right) (make-instance square :xlow (x-coordinate lower-left) :ylow (y-coordinate lower-left) :xhigh (x-coordinate upper-right) :yhigh (y-coordinate upper-right)))
which would replace the original constructor function:
(defun make-square (lower-left upper-right) (make-instance square :lower-left lower-left :upper-right upper-right))
5.4.8.2. Changing the Class of an Instance
When an instance is changed to a new class, the slots have the following update behavior:
As in updating an instance for a redefined class, instances can be updated by defining a method for update-instance-for-redefined-class. This generic function takes as arguments a copy of the instance before it was updated and the updated instance. Because the original class still exists unchanged, the copy of the instance before it was updated can be accessed using slot-value or any of the accessors defined in the original class.
As in updating an instance for a redefined class, this is normally done by using before methods or after methods.
This section shows some techniques for extending CLOS. These use the MOP and de facto extensions for CLOS described in Part II of The Art of the Metaobject Protocol (Kizcales, Rivieres, Bobrow, 1991), implemented by most Common Lisp systems. For an excellent description of how a MOP is implemented, see The Art of the Metaobject Protocol (Kizcales, Rivieres, Bobrow, 1991). Note that this reference is a simplified form of the MOP for teaching purposes.
Every ordinary CLOS class is an instance of a system-supplied class metaobject class (or metaclass). This particular metaclass is called standard-class and, like all other CLOS objects, it has slots, values, and methods. When you made the class cookies-n-cream, an object was made that completely describes the cookies-n-cream class. The slots and values in this object are determined by standard-class. The following shows what the metaclass object might look like:
Slot | Value |
---|---|
Name | cookies-n-cream |
Direct superclasses | (vanilla oreos edible standard-object t) |
Direct slots | () |
Effective slots | fat-content |
Direct subclasses | () |
Class | standard-object |
5.4.9.1. Very Large Spreadsheets and Dependency Tracking
This section outlines two techniques often used in CAD applications.
As an example, Boeing designs very large planes using classes and instances to model the aircraft. Designers at Boeing iterate over a plane design by changing properties of objects in the model. It is often convenient to model the object properties as slot values of the object. However, many properties are often dependent on the slot values in other objects. For example, the seating capacity of the plane may be calculated from the height and width and length of the passenger compartment, but the length of the plane may be dependent on other dimensions of components of the plane.
Designing a plane is like manipulating a very large spreadsheet, where changing the value in a cell necessitates an update to other cell values that are calculated using the changed value. As in a spreadsheet, you want the system to automatically keep track of all the formulas defining the slot values of objects and their dependencies on other values.
Two cases have different semantics for tracking and updating such dependencies. In one case, when you change a value, you need to know all the dependent values immediately. For example, if a plane is being drawn on the screen, then changing a property should immediately result in all the dependent properties being updated correctly so that the view on the screen remains consistent.
Immediate update becomes impractical when the models are large. While working on one aspect of the model (say the seating arrangement), you may not need other parts of the model. In this case, to improve performance, it is better to defer updating the other parts of the model until they are needed.
Well discuss the first case first.
Dependency Tracking Applied to Immediate Update
First of all, use the following code so that the functions for the metaobject protocols are visible in the current package:
(use-package :clos)
Now define a new type of metaclass by subclassing standard-class. All the classes in the model use the semantics of this metaclass:
(defclass dependency-class (standard-class) ())
At this point, you can make new classes of this type:
(defclass part () ((dependency :initform nil :accessor part-dependency)) (:metaclass dependency-class)) (defclass body (part) ((length :reader lngth) (width :initform 0 :accessor width)) (:metaclass dependency-class)) (defclass wing (part) ((length :initform 0 :accessor lngth)) (:metaclass dependency-class))
Previous | Table of Contents | Next |