Книга: Practical Common Lisp
DEFGENERIC
DEFGENERIC
To give you a feel for these macros and the various facilities they support, I'll show you some code you might write as part of a banking application—or, rather, a toy banking application; the point is to look at a few language features, not to learn how to really write banking software. For instance, this code doesn't even pretend to deal with such issues as multiple currencies let alone audit trails and transactional integrity.
Because I'm not going to discuss how to define new classes until the next chapter, for now you can just assume that certain classes already exist: for starters, assume there's a class bank-account
and that it has two subclasses, checking-account
and savings-account
. The class hierarchy looks like this:
The first generic function will be withdraw
, which decreases the account balance by a specified amount. If the balance is less than the amount, it should signal an error and leave the balance unchanged. You can start by defining the generic function with DEFGENERIC
.
The basic form of DEFGENERIC
is similar to DEFUN
except with no body. The parameter list of DEFGENERIC
specifies the parameters that must be accepted by all the methods that will be defined on the generic function. In the place of the body, a DEFGENERIC
can contain various options. One option you should always include is :documentation
, which you use to provide a string describing the purpose of the generic function. Because a generic function is purely abstract, it's important to be clear to both users and implementers what it's for. Thus, you might define withdraw
like this:
(defgeneric withdraw (account amount)
(:documentation "Withdraw the specified amount from the account.
Signal an error if the current balance is less than amount."))