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:
(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)