Generic function in
CLOS are the closest thing to "messages".
Instead of writing
(SEND instance operation-name arg*)
(operation-name instance arg*)
The operations / messages are generic functions -- functions whose behavior can be defined for instances of particular classes by defining methods.
(DEFGENERIC function-name lambda-list) can be used to define a generic
function. You don't have to call
DEFGENERIC, however, because
automatically defines the generic function if it has not been defined
already. On the other hand, it's often a good idea to use
as a declaration that an operation exists and has certain parameters.
Anyway, all of the interesting things happen in methods. A method is defined by:
(DEFMETHOD generic-function-name specialized-lambda-list form*)
This may look fairly cryptic, but compare it to
DEFUN described in
a similar way:
(DEFUN function-name lambda-list form*)
A "lambda list" is just a list of formal parameters, plus things like
&REST. It's because of such
complications that we say
"lambda-list" instead of "(parameter*)"
when describing the syntax.
[I won't say anything
&KEY in methods.
The rules are in CLtL2 or the HyperSpec, if you want to know them.]
So a normal function has a lambda list like
(var1 var2 ...).
A method has one in which each parameter can be "specialized"
to a particular class. So it looks like:
((var1 class1) (var2 class2) ...)
The specializer is optional. Omitting it means that the method
can apply to instances of any class, including classes that were
not defined by
DEFCLASS. For example:
(defmethod change-subject ((teach teacher) new-subject) (setf (teacher-subject teach) new-subject))
Here the new-subject could be any object. If you want to restrict it, you might do something like:
(defmethod change-subject ((teach teacher) (new-subject string)) (setf (teacher-subject teach) new-subject))
Or you could define classes of subjects.
Methods in "classical" object-oriented programming specialize
only one parameter. In
CLOS, you can specialize more than one.
If you do, the method is sometimes called a multi-method.
A method defined for a class
C overrides any method defined
for a superclass of
C. The method for
than the method for the superclass, because
C is more specific
that the classes it inherits from (eg, dog is more specific
For multi-methods, the determination of which method is more specific involves more than one parameter. The parameters are considered from left to right.
(defmethod test ((x number) (y number)) '(num num)) (defmethod test ((i integer) (y number)) '(int num)) (defmethod test ((x number) (j integer)) '(num int)) (test 1 1) => (int num), not (num int) (test 1 1/2) => (int num) (test 1/2 1) => (num int) (test 1/2 1/2) => (num num)