如何"cast"一个实例到一个子类?

How to "cast" an instance to a subclass?

我有一个 class 消息的实例,我将调用 "msg"。我已经定义了一个 class "my-message" 并希望实例 "msg" 现在属于 class.

听起来应该比较简单,但我不知道该怎么做。 change-class 给我一个我不明白的错误。

(defclass my-message (message)
  ((account-name :accessor account-name :initform nil :initarg :account-name)))

(change-class msg 'my-message :account-name account-name)

ERROR :
While computing the class precedence list of the class named MW::MY-MESSAGE.
The class named MW::MESSAGE is a forward referenced class.
The class named MW::MESSAGE is a direct superclass of the class named MW::MY-MESSAGE.
The class named MW::MESSAGE is a forward referenced class.

前向引用 class 是您引用但尚未定义的 class。如果您查看 class 的名称,它是 MW::MESSAGE。我想你想在另一个包中子 class 另一个名为 MESSAGE 的 class;您导入的符号可能有问题。

The class named MW::MESSAGE is a direct superclass of the class named MW::MY-MESSAGE.

由于 MW::MESSAGE class 尚未定义,您无法创建它的实例。这也是为什么你不能创建它的任何子 class 实例的原因,例如 MW::MY-MESSAGE.

这对我有用:

CL-USER>  (defclass message () ())
#<STANDARD-CLASS COMMON-LISP-USER::MESSAGE>

CL-USER> (defparameter *msg* (make-instance 'message))
*MSG*

CL-USER> (describe *msg*)
#<MESSAGE {1002FE43F3}>
  [standard-object]
No slots.


CL-USER> (defclass my-message (message)
           ((account-name :accessor account-name
                          :initform nil
                          :initarg :account-name)))
#<STANDARD-CLASS COMMON-LISP-USER::MY-MESSAGE>

CL-USER> (change-class *msg* 'my-message  :account-name "foo")
#<MY-MESSAGE {1002FE43F3}>

CL-USER> (describe *msg*)
#<MY-MESSAGE {1002FE43F3}>
  [standard-object]

Slots with :INSTANCE allocation:
  ACCOUNT-NAME  = "foo"

请注意,这不是 cast,因为对象本身将被更改。它现在是另一个 class 的实例。 casting 通常意味着只是对未更改事物的解释在某些上下文中发生了变化。但是这里的实例真的变了,旧的解释不再适用。