Common Lisp § Multiple dispatch
;; Define the generic function first. (defgeneric draw (shape) (:documentation "docstring.")) ;; Next, define methods (i.e., generic function implementations) (defmethod draw ((shape circle)) ...) (defmethod draw ((shape triangle)) ...) ;; If there are multiple matching, a method can call ;; `call-next-method' to execute the next implementation. (defmethod withdraw ((account checking-account) amount) ...some code... (call-next-method))
Common Lisp has primary and auxiliary methods. Auxiliary methods can be defined with
(defmethod withdraw :before ((account bank-account) amount) ...) (defmethod withdraw :after ((account bank-account) amount) ...) (defmethod withdraw :around ((account bank-account) amount) ...)
All around methods in the order from most specific to less specific. Around methods should call
When the least specific around method calls
call-next-method, that executes:
All before methods in the order from most specific to least specific.
Primary method may call
call-next-methodto execute the next less specific primary method.
All after methods in the order from least specific to most specific (reverse order of before).
Be default, primary methods completely override less specific primary methods (although they can be executed with
call-next-method). Common Lisp also has nine other combinations:
progn—they wrap all primary methods in the specified function/macro/operator. (New method combinations can be added with
If method combination is used, only primary and
:around methods are supported.
(defgeneric priority (job) (:method-combination +)) ;; :most-specific-last can be added to reverse the order of primary ;; methods (does not affect :around methods) ;; `defmethod' must also specify the method combination. (defmethod priority + ((job express-job)) 10)
It is possible to create methods that specialize on a particular object with an
(defmethod withdraw ((account (eql *account-of-bank-president*)) amount) ...)
The object in
eql specializer is evaluated once only (i.e., if the value of that variable changes, the method won't change).