I’ve seen this “anti-pattern” a few times in CLOS
code. A superclass ’super
will have a
subclass ’sub
and there will be a primary method
specialized to the superclass.
(defmethod foo ((instance super) arg) (format t "~&Foo called on ~s." arg))
Then I’ll see an :around
method defined on the
subclass:
(defmethod foo :around ((instance sub) arg) (format t "~&Start foo...~%") (call-next-method) (format t "~&End foo.~%"))The intent here is clearly that code in the method specialized on the subclass is invoked “around” the call to the method specialized on the superclass.
But the :around
qualifier is not necessary and
probably doesn’t do what is intended. If we remove
the :around
qualifier, then the most specific primary
method will be the foo method specialized
on ’sub
. And the (call-next-method)
invokation will chain up to the foo method specialized
on ’super
. It will work as was likely intended.
:around
methods are useful when
the superclass wants to run a method “around”
the subclass. :around
methods are combined from least
specific to most specific — the opposite order of primary
methods — so that the superclass can wrap the call to the
subclass. An good example of where an :around
method
would be handy is when you need to sieze a lock around the call to
the method. The superclass would sieze the lock in
an :around
method that would run before any of the
subclass primary methods ran.
Ordinary chaining of methods doesn’t need
the :around
qualifier. Just chain the methods.
No comments:
Post a Comment