我不确定我理解你的问题。答案几乎肯定是在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)))
(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)))
(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))
...)
initialize-instance
的后续方法中从一个初始化另一个。 - ignis volensinitialize-instance
方法将会做他们原本就该做的事情:这就是为什么它们是后续方法。我建议你实际尝试一些例子(放置调用print
或其他你想要的内容来查看发生了什么),而不是简单地猜测可能会发生什么。 - ignis volens