"overriding" :超类的 defclass 中的 initform 设置 (CLOS)

"overriding" :initform setting in defclass for superclass (CLOS)

我有一个用 :initform

定义的 class
(defclass A()
  ((MI :initarg :mi :initform (error "must specify mi") ) ) )

它带有一个初始化实例 :after 方法来计算一些东西(太长而无法显示);该计算的最终结果与 class A 和派生的 class B 相关;见下文)

和派生的 class

(defclass B(A)
  (( ABC :initarg :abc :initform (error "must specify abc") ) ) ) 

现在,class B 需要在其各自的初始化实例方法中执行与 A 相同的计算;但是,在这种情况下,A 中的参数 mi 是 B 中 ABC 的函数。

所以我尝试在 B 的初始化实例中计算一个 "temporary mi";没用

我尝试计算 mi,将其存储在 B 的 ABC 的局部变量 mitmp 中并调用 (call-next-method mitmp);没用

我试图在 B 中定义另一个 MI 字段,而不像在 A 中那样使用 :initform。我希望我能够在 B 的初始化实例中的 let-form 中计算 mi;也没用。

[使用像 C++ 这样的 Blub 语言,这就可以了;不知何故,我一直坚持这种思维方式。]

所以我剩下的问题是 "how can I have B to have a mandatory argument ABC that than is "transformed" 变成强制性的 A 的 mi 并赋予 A 的初始化实例。

欢迎任何提示。

[编辑:澄清了一些事情]

您可以在 b 上定义一个 :before 方法 initialize-instance。如果您使用 :after 方法,它只会在 a 已经初始化后获得 运行。一个简单的例子:

(defclass a ()
  ((mi :initarg :mi :initform (error "Must specify mi"))
   (computed-value :accessor computed-value)))

(defmethod initialize-instance :after ((a a) &key)
  (with-slots (mi computed-value) a
    (setf computed-value (* mi 2))))

(defclass b (a)
  ((abc :initarg :abc :initform (error "must specify abc"))))

(defmethod initialize-instance :before ((b b) &key (abc 1 abc-p))
  ;; You have to check that ABC was given manually, since this is
  ;; run before initialising B. You wouldn't necessarily even 
  ;; need to have a slot for ABC if you don't need it for anything 
  ;; else.
  (unless abc-p (error "Must specify abc"))
  (setf (slot-value b 'mi) (+ abc 10)))

(computed-value (make-instance 'a :mi 4))
; => 8
(computed-value (make-instance 'b :abc 4))
; => 28