Brief Guide to CLOS: Generic functions and methods

## 6. Generic functions and methods

Generic function in `CLOS` are the closest thing to "messages". Instead of writing

> `

>     (SEND instance operation-name arg*)

> `

you write

> `

>     (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 `DEFMETHOD` automatically defines the generic function if it has not been defined already. On the other hand, it's often a good idea to use `DEFGENERIC` 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 `&OPTIONAL` or `&REST`. It's because of such complications that we say "lambda-list" instead of "(parameter*)" when describing the syntax.

[I won't say anything about `&OPTIONAL` , `&REST`, or `&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 `C` is "more specific" than the method for the superclass, because `C` is more specific that the classes it inherits from (eg, dog is more specific than animal).

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)

> `