我不确定我是否理解您的问题。我认为答案几乎肯定是在initialize-instance 上的方法之后。你说这会导致在超类中定义的槽首先被初始化:是的,它会,而且几乎可以肯定你想要发生的事情。超类中定义的插槽通常不依赖于子类插槽的值(它总是可以考虑所有事物的异常),因此以最不具体的一阶初始化几乎总是您想要的。
我使用的初始化槽的两种常用方法是简单地在定义中声明它们的 initargs 是什么:
(defclass minibeast ()
((legs :initform 'uncountable
:initarg :legs
:initarg :leg-count
:accessor legs)
(tentacles :initform 'many
:initarg :tentacles
:initarg :number-of-tentacles
:accessor tentacles)))
现在(make-instance 'minibeast :legs 87) 可以满足您的期望。这很有效(因为,如果两个插槽是在不同的类中定义的,显然它必须这样做):
(defclass awful-monster ()
((legs :initform 'uncountable
:initarg :legs
:initarg :leg-count
:accessor legs)
(appendages :initform 'many
:initarg :legs
:initarg :appendages)))
现在(make-instance 'awful-monster :legs 93) 将产生一个拥有 93 条腿和 93 个附肢的可怕怪物。
但是,该方法可能不符合将接口与实现分开的条件。您可能还想在初始化插槽时执行一些计算。在这两种情况下,initialize-instance 上的方法通常是正确的方法:
(defclass horrible-monster ()
((legs :initform 983
:accessor legs)
(eyes :initform 63
:accessor eyes)
(appendages
:reader appendages)))
(defmethod initialize-instance :after
((m horrible-monster) &key eyes legs (stalky-eyes t))
(with-slots ((e eyes) (l legs) appendages) m
(when eyes (setf e eyes))
(when legs (setf l legs))
(setf appendages (if stalky-eyes (+ e l) l))))
现在可怕的怪物会得到适当数量的附属物(我不知道为什么可怕的怪物不知道他们的眼睛是否在茎上:也许他们没有镜子)。
当然还有许多其他组合。您可能不想让用户代码显式调用make-instance,而是将其封装在某个函数中:
(defun make-awful-thing (&rest args &key (sort-of-horrible-thing 'horrible-monster)
&allow-other-keys)
(let ((the-remaining-args (copy-list args)))
;; No doubt alexandria or something has a way of doing this
(remf the-remaining-args ':sort-of-horrible0thing)
(apply #'make-instance sort-of-horrible-thing the-remaining-args)))
现在,您当然可以轻松拥有一些定制的初始化协议:
(defgeneric enliven-horrible-thing (horrible-thing &key)
(:method :around ((horrible-thing t) &key)
(call-next-method)
t))
(defun make-awful-thing (&rest args &key (sort-of-horrible-thing 'horrible-monster)
&allow-other-keys)
(let ((the-remaining-args (copy-list args)))
;; No doubt alexandria or something has a way of doing this
(remf the-remaining-args ':sort-of-horrible0thing)
(apply #'enliven-horrible-thing
(apply #'make-instance sort-of-horrible-thing
the-remaining-args)
the-remaining-args)))
(defmethod enliven-horrible-thing ((horrible-thing horrible-monster)
&key (ichor t) (smell 'unspeakable))
...)