Previous Next Contents

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

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) 

Previous Next Contents