Brief Guide to CLOS: Method combination.

## 7. Method combination.

When more than one class defines a method for a generic function, and more than one method is applicable to a given set of arguments, the applicable methods are combined into a single "effective method". Each individual method definition is then only part of the definition of the effective method.

One kind of method combination is always supported by `CLOS`. It is called standard method combination. It is also possible to define new kinds of method combination. Standard method combination involves four kinds of methods:

- Primary methods form the main body of the effective method. Only the most specific primary method is called, but it can call the next most specific primary method by calling

  > `

  >     (call-next-method)

  > `

- `:BEFORE` methods are all called before the primary method, with the most specific `:BEFORE` method called first.
- `:AFTER` methods are all called after the primary method, with the most specific `:AFTER` method called last.
- `:AROUND` methods run before the other methods. As with primary methods, only the most specific is called and the rest can be invoked by `CALL-NEXT-METHOD`. When the least specific `:AROUND` method calls `CALL-NEXT-METHOD`, what it calls is the combination of `:BEFORE`, `:AFTER`, and primary methods.

`:BEFORE`, `:AFTER`, and `:AROUND` methods are indicated by putting the corresponding keyword as a qualifier in the method definition. `:BEFORE` and `:AFTER` methods are the easiest to use, and a simple example will show how they work:

> `

>     (defclass food () ())

>     (defmethod cook :before ((f food))
>       (print "A food is about to be cooked."))

>     (defmethod cook :after ((f food))
>       (print "A food has been cooked."))

>     (defclass pie (food)
>       ((filling :accessor pie-filling :initarg :filling :initform 'apple)))

>     (defmethod cook ((p pie))
>       (print "Cooking a pie")
>       (setf (pie-filling p) (list 'cooked (pie-filling p))))

>     (defmethod cook :before ((p pie))
>       (print "A pie is about to be cooked."))

>     (defmethod cook :after ((p pie))
>       (print "A pie has been cooked."))

>     (setq pie-1 (make-instance 'pie :filling 'apple))

> `

And now:

> `

>     <cl> (cook pie-1)
>     "A pie is about to be cooked."
>     "A food is about to be cooked."
>     "Cooking a pie"
>     "A food has been cooked."
>     "A pie has been cooked."
>     (cooked apple)

> `