有一个通用的方法,比如说incx
。有两个版本incx
。一种专门针对类型a
,一种专门针对类型b
。类型b
是 的子类a
。给您一个类型的对象b
,即派生类型,但您想调用专门针对类型的方法a
。如果还没有专门针对 type 的同名方法,您可以轻松地做到这一点b
,但是唉,有这样的方法。
a
那么在这种情况下如何调用专门针对类型的方法呢?
(defclass a () ((x :accessor x :initform 0)))
(defclass b (a) ((y :accessor y :initform 0)))
(defgeneric inc (i))
(defmethod inc ((i a)) (incf (x i)))
(defmethod inc ((i b)) (incf (y i)))
(defvar r (make-instance 'b))
正如 CLOS 所承诺的,这调用了最专业的方法:
* (inc r)
* (describe r)
..
Slots with :INSTANCE allocation:
X = 0
Y = 1
但在这种特殊情况下,(不是一般情况下)我想要的是访问不太专业的版本。像这样说:
(inc (r a)) ; crashes and burns of course, no function r or variable a
(inc a::r) ; of course there is no such scoping operator in CL
我看到call-next-method
可以在专门的方法中使用该函数来获得下一个不那么专门的方法,但这不是这里想要的。
在被剪掉的代码中,我确实需要类似于 的东西call-next-method
,但用于调用补充方法。与其在下一个不太专业化的类中调用同名方法,不如调用它的互补方法,该方法具有不同的名称。补充方法也是专门的,但调用这个专门的版本不起作用 - 原因call-next-method
可能与包含的原因大致相同。专用于超类的所需方法并不总是具有相同的名称。
(call-next-method my-complement) ; doesn't work, thinks my-complement is an arg
这是另一个例子。
有一个描述电子特性的基类和一个描述“奇怪电子”特性的派生类。专门研究奇怪电子的方法希望调用专门研究电子的方法。为什么?因为这些方法为程序完成了正常电子部分的工作。奇怪电子的非电子部分几乎是微不足道的,或者更确切地说,如果它没有复制电子代码:
(defgeneric apply-velocity (particle velocity))
(defgeneric flip-spin (particle))
;;;; SIMPLE ELECTRONS
(defclass electron ()
((mass
:initform 9.11e-31
:accessor mass)
(spin
:initform -1
:accessor spin)))
(defmacro sq (x) `(* ,x ,x))
(defmethod apply-velocity ((particle electron) v)
;; stands in for a long formula/program we don't want to type again:
(setf (mass particle)
(* (mass particle) (sqrt (- 1 (sq (/ v 3e8)))))))
(defmethod flip-spin ((particle electron))
(setf (spin particle) (- (spin particle))))
;;;; STRANGE ELECTRONS
(defclass strange-electron (electron)
((hidden-state
:initform 1
:accessor hidden-state)))
(defmethod flip-spin ((particle strange-electron))
(cond
((= (hidden-state particle) 1)
(call-next-method)
;; CALL ELECTRON'S APPLY-VELOCITY HERE to update
;; the electron. But how???
)
(t nil)))
;; changing the velocity of strange electrons has linear affect!
;; it also flips the spin without reguard to the hidden state!
(defmethod apply-velocity ((particle strange-electron) v)
(setf (mass particle) (* (/ 8 10) (mass particle)))
;; CALL ELECTRON'S SPIN FLIP HERE - must be good performance,
;; as this occurs in critical loop code, i.e compiler needs to remove
;; fluff, not search inheritance lists at run time
)
这一切都归结为一个简单的问题:
如果定义了更专业的方法,如何调用不太专业的方法?