The name of a SETF function is a two-item list whose first element is the symbol setf and whose second element is a symbol, typically the name of a function used to access the place the SETF function will set. Common Lisp also supports multiple inheritance--a class can have multiple direct superclasses, inheriting applicable methods and slot specifiers from all of them.
Or, as the man page for Perl's object system puts it, "Now you need just to go off and buy a book about object-oriented design methodology and bang your forehead with it for the next six months or so.
The function and method created follow the requirements for a SETF function, taking the new value as the first argument and returning it as the result, so you can define a SETF function by providing a name such as setf customer-name. This complicates the notion of class specificity that's used both when building the effective methods for a generic function and when merging inherited slot specifiers.
Everything else you might want to do can be implemented in terms of those two functions. And a sub-subclass may then redefine it back to: To see how this works, let's add a class to the banking app: For instance, since a slot can have only a single default value, if multiple classes specify an: I'll discuss them in a bit more detail in Chapter Common Lisp resolves these situations by merging all the specifiers with the same name from the new class and all its superclasses to create a single specifier for each unique slot name.
Any attempt to get the value of an unbound slot signals an error, so you must set a slot before you can read it.
If you do that, you'll get a new primary method that shadows the default one. Both of these methods will be applicable to instances of money-market-account, but the one specialized on checking-account will be considered more specific than the one on savings-account because checking-account precedes savings-account in money-market-account's class precedence list.
This class defines no slots of its own but will inherit slots from both of its direct superclasses, including the slots they inherit from their superclasses. Then, print-statement, called on a money-market-account, will print a basic account statement, output by the primary method specialized on bank-account, followed by details output by the: It's trivial to define a function that reads the value of the balance slot.
Multiple Inheritance All the classes you've seen so far have had only a single direct superclass. Classes also inherit slots from their superclasses, but the mechanism is slightly different. The rest of the representation is implementation-defined but will typically be something like the output just shown, including the name of the class and some distinguishing value such as the address of the object in memory.
However, it's also possible to inherit different methods for the same generic function from different superclasses. Likewise, any method that's applicable to any class in the class precedence list will be applicable to a money-market-account object. That is, if classes could have only a single direct superclass, ordering classes by specificity would be trivial--a class and all its superclasses could be ordered in a straight line starting from the class itself, followed by its single direct superclass, followed by its direct superclass, all the way up to T.
The wrinkle that multiple inheritance adds is that a class can have more than one direct superclass. That way, you can provide different methods on balance for those subclasses or extend its definition with auxiliary methods. On the other hand, if you don't care exactly what the order is but want it to be consistent across several generic functions, then using auxiliary methods may be just the thing.
A SETF function can take any number of arguments, but the first argument is always the value to be assigned to the place. The disadvantage is that you don't get fine-grained control over the order in which the auxiliary methods run--if you wanted the checking-account part of the statement to print before the savings-account part, you'd have to change the order in which the money-market-account subclasses those classes.
For instance, you could provide reader and writer methods for customer-name equivalent to the ones you just wrote by changing the slot specifier to this: But that's a fairly define time slots change that could affect other methods and inherited slots.
For example, suppose you decide to change the definition of bank-account so that, instead of storing the current balance as a number, you store a list of time-stamped withdrawals and deposits. The problem is that while you can use CALL-NEXT-METHOD to call "up" to the next most specific method, namely, the one specialized on checking-account, there's no way to invoke a particular less-specific method, such as the one specialized on savings-account.
At the minimum, a slot specifier names the slot, in which case the slot specifier can be just a name. In that case, the class precedence list does come into play.
For instance, suppose the banking application defined a generic function print-statement used to generate monthly statements. When a slot has: To access the a slot on either a foo or a bar, you'll continue to use the generic function a.
The instance-form is evaluated once to produce the object whose slots will be accessed. In Common Lisp a given object can have only one slot with a particular name. Usually merging slot definitions works quite nicely. Putting it all together and adding a reader method for the account-number and account-type slots, the DEFCLASS form for the bank-account class would look like this: