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

时间:2013-12-26 01:45:09

标签: lisp common-lisp clos

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

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

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

和方法:

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

现在,我想打印'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 "))

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

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

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

3 个答案:

答案 0 :(得分: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 "))

答案 1 :(得分:5)

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

<强> CALL-NEXT-METHOD

您可以调用下一个适用的方法:CALL-NEXT-METHOD。请注意,您不能以这种方式调用特定方法,只能调用下一个方法。大部分时间这都是人们在CLOS中使用的。然后,在方法定义期间,任务是使用主要的:around:before:after方法以这种方式设置通用函数,从而产生正确的行为。

在所有其他方法失败时调用特定功能

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

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

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

答案 2 :(得分:0)

按照Sonya Keene的过程锁定示例(COMMON LISP中的面向对象编程:CLOS程序员指南),您可以使用:after方法

(defmethod print-object ((a1 a) stream)
  (format stream "instance of A ")) 
(defmethod print-object :after ((b1 b) stream)
  (format stream "instance of B "))

这将给出

CL-USER> (make-instance 'b)
    instance of A instance of B