我无法确定这是否可行,只是使用了一个(相当丑陋)的解决方法。
假设我们有一个类结构如下:
(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?
答案 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