1

我不知道这是否可能,只是使用了一个(相当丑陋的)解决方法。

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

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

和方法:

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

现在,我想为 'a 调用 print,然后为 'b 调用 print,假设存在“类型转换”函数:

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

我的解决方法是在 b 的打印对象中创建一个类型为 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 的解决方案?

4

3 回答 3

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 "))
于 2013-12-26T03:26:41.670 回答
6

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 的一部分,而是由元对象协议 (MOP)在许多实现中提供的。

于 2013-12-26T07:28:56.487 回答
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 
于 2013-12-29T14:22:25.873 回答