Search code examples
lispcommon-lispclos

Calling another overloaded method in Lisp


I couldn't find out if this was possible, and just used a (rather ugly) workaround.

Assume we've got a class structure as below:

(defclass a () ())
(defclass b (a) ())

and the method:

(defmethod print-object ((a1 a) stream)
 (format stream "instance of A "))

now, I want to call print for 'a then print for 'b, assuming a "type-cast" function exists:

(defmethod print-object ((b1 b) stream)
 (prin1 (type-cast b1 'a) stream)
 (format stream "instance of B "))

My workaround is to create an object of type a within print-object of b, then call prin1

(defmethod print-object ((b1 b) stream)
 (let ((a1 (make-instance 'a)))
    (prin1 a1 stream))
 (format stream "instance of B "))

I tried coerce and ended up with infinite loop. I just realized I can try using find-method and call-method (would it work?). Or should I try a solution with :around?


Solution

  • COERCE does not work with CLOS objects. You can change the class of an instance with CHANGE-CLASS, but that's usually not a good idea.

    CALL-NEXT-METHOD

    You can call the next applicable method: CALL-NEXT-METHOD. Note that you can't call a specific method that way, just the next one. Most of the time this is what one would use in CLOS. The task is then during method definition to set up the generic function in such a way, using primary, :around, :before and :after methods, that the right behavior emerges.

    Calling specific functions when all else fails

    There is an esoteric way to call a specific method:

    (funcall (method-function (find-method #'print-object
                                           nil
                                           (list (find-class 'a)
                                                 (find-class t))))
             (make-instance 'b)
             t)
    

    In above code, the function METHOD-FUNCTION is not part of ANSI Common Lisp, but provided in many implementations by the Metaobject Protocol (MOP).