在Lisp中调用另一个重载方法

Alb*_*glu 1 lisp common-lisp clos

我无法确定这是否可行,只是使用了一个(相当丑陋)的解决方法.

假设我们有一个类结构如下:

(defclass a () ())
(defclass b (a) ())
Run Code Online (Sandbox Code Playgroud)

和方法:

(defmethod print-object ((a1 a) stream)
 (format stream "instance of A "))
Run Code Online (Sandbox Code Playgroud)

现在,我想打印'a a then print for'b,假设存在"type-cast"函数:

(defmethod print-object ((b1 b) stream)
 (prin1 (type-cast b1 'a) stream)
 (format stream "instance of B "))
Run Code Online (Sandbox Code Playgroud)

我的解决方法是在b的print-object中创建一个a类型的对象,然后调用prin1

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

我试图强迫并最终得到无限循环.我刚刚意识到我可以尝试使用find-method和call-method(它会起作用吗?).或者我应该尝试解决方案:周围?

mon*_*oid 6

Coerce不会创建新对象,因为b1已经具有类型(子类型)a.

您所需要的只是call-next-method:

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

(defmethod print-object ((b1 b) stream)
   (call-next-method) ; by default same arguments are used: b1 and stream
   (format stream "instance of B "))
Run Code Online (Sandbox Code Playgroud)


Rai*_*wig 5

COERCE不适用于CLOS对象.您可以使用更改实例的类CHANGE-CLASS,但这通常不是一个好主意.

CALL-NEXT-METHOD

您可以调用下一个适用的方法:CALL-NEXT-METHOD.请注意,您不能以这种方式调用特定方法,只能调用下一个方法.大部分时间这都是人们在CLOS中使用的.然后,在方法定义期间,任务是以这样的方式设置泛型函数,使用primary :around,:before:after方法,正确的行为出现.

所有其他方法都失败时调用特定函数

调用特定方法有一种深奥的方法:

(funcall (method-function (find-method #'print-object
                                       nil
                                       (list (find-class 'a)
                                             (find-class t))))
         (make-instance 'b)
         t)
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,该函数METHOD-FUNCTION不是ANSI Common Lisp的一部分,但是在Metaobject Protocol(MOP)的许多实现中提供.