如何在具有多个关键参数 CLOS 的初始化实例中使用调用下一个方法

How to use call-next-method in initialize-instance with multiple key arguments CLOS

如果我有两个 class,一个 class parent 和一个 class child.

(defclass parent ()
    ...)

(defclass child (parent)
    ...)

我已经为初始化实例定义了 2 种不同的方法,但是子方法接受了另一个参数,并调用了 call-next-method

(defmethod initialize-instance :after ((instance parent) &key)
    ...) ; Do things

(defmethod initialize-instance :after ((instance child) &key other-arg)
    ... ; Do things
    (call-next-method))

我收到错误

There is no next method for the generic function
#<STANDARD-METHOD COMMON-LISP:INITIALIZE-INSTANCE (93)>
when called from method
#<STANDARD-METHOD COMMON-LISP:INITIALIZE-INSTANCE :AFTER (CHILD) {...}>
with arguments
 ....

Condition of type SB-PCL::NO-NEXT-METHOD-ERROR

显然,我无法使用提供的参数调用下一个方法?

您是否引用了您的 post 中未提及的方法?错误消息提到了 :after 方法。也许您可以启动一个新的 sbcl 实例并在那里重新创建 类 和方法,只是为了确保同样的问题仍然存在?

我试着像这样填补你代码中的空白:

(defclass parent ()
  nil)

(defclass child (parent)
  nil)

(defmethod initialize-instance ((instance parent) &key)
  (format t "~&Init parent."))

(defmethod initialize-instance ((instance child) &key other-arg)
  (format t "Init child with ~a." other-arg)
  (call-next-method))

CL-USER> (make-instance 'parent)
Init parent.
#<PARENT {100390DEE3}>
CL-USER> (make-instance 'child)
Init child with NIL.
Init parent.
#<CHILD {100390AB93}>
CL-USER> (make-instance 'child :other-arg 'foo)
Init child with FOO.
Init parent.
#<CHILD {100396D253}>

以上似乎适用于我的设置。
它对你有用吗?

在您使用的 standard method combination 中,after 方法没有 next 方法,因此 call-next-method 不能在其中使用:在方法全部调用后更适用按照方法组合的最具体最后顺序。允许您使用的地方 call-next-method 是主要方法和周围方法。