Search code examples
common-lispsbclclosgeneric-functionmethod-combination

Understanding CLOS :after and primary methods


In the hunchentoot source code, there is an :after defmethod called initalize-instance.

This particular example is one of a handful of :after methods called initalize-instance throughtout the project.

My experience with CLOS taught me that a primary method is required for :before, :after and :around methods can be used.

But in the hunchentoot package, I cannot see how they have created the primary methods to allow the :after methods to work.

What am I missing?


Solution

  • The symbol initalize-instance is in the COMMON-LISP package. It is one of the generic functions provided by the standard. If you check this generic function, you'll find that it has many methods. There is also a matching primary method. Methods can be declared anywhere, they don't need to be in a particular file.

    CL-USER 9 > (defclass my-class () (a b))
    #<STANDARD-CLASS MY-CLASS 8010021793>
    
    CL-USER 10 > (defmethod initialize-instance :after ((instance my-class)
                                                        &rest initargs &key)
                   (print `(:aftermethod for initialize-instance
                            of class my-class
                            and instance ,instance)))
    #<STANDARD-METHOD INITIALIZE-INSTANCE (:AFTER) (MY-CLASS) 8010027193>
    
    CL-USER 11 > (make-instance 'my-class)
    
    (:AFTERMETHOD FOR INITIALIZE-INSTANCE OF CLASS
     MY-CLASS AND INSTANCE #<MY-CLASS 80103A979B>) 
    #<MY-CLASS 80103A979B>
    

    The method combination for initialize-instance with an object of class my-class looks like this:

    MULTIPLE-VALUE-PROG1
     CALL-METHOD
      (METHOD INITIALIZE-INSTANCE (STANDARD-OBJECT))
     CALL-METHOD
      (METHOD INITIALIZE-INSTANCE :AFTER (MY-CLASS))
    

    The primary method for STANDARD-OBJECT is system provided.

    CL-USER 12 > (typep * 'standard-object)
    T
    

    Above shows that the instance is also of class standard-object, because standard-object is a superclass of my-class.

    CL-USER 13 > (class-direct-superclasses (find-class 'my-class))
    (#<STANDARD-CLASS STANDARD-OBJECT 80D01BCA7B>)
    

    The class standard-object is a superclass of the class my-class.