《实用Common Lisp编程》第16-17章,面向对象细节补遗(1):辅助方法
在《实用common lisp编程》的十六和十七章里面,介绍了common lisp的面向对象支持方式,分别是广义函数和CLOS系统。
?
书本通过文字叙述得非常详细,但是没有附上相应的代码,本着“没有实验过就没有发言权”的求实态度,我决定从带修饰符的辅助方法、带继承的方法、继承和槽、以及多继承等几个主要知识点着手,在代码方面实现一遍,验证书中的内容。
?
带辅助方法的主方法
?
第十六章介绍了几个广义函数的修饰符,主要有 :around , :before 和 :after ,而被装饰符修饰的方法称之为“主方法”(primary method),它们的一般运行顺序如下:
?
1.如果被调用的主方法有 :around 辅助方法,先运行 :around ,在 :around 运行之后,有两种选择,一种是,不调用 call-next-method ,那么整个函数就宣告结束,主方法不会被运行。
?
另一方面,如果 :around 调用 call-next-method ,这时又出现两种情况:
1) 该主方法还有一个最相关的 :around 辅助方法,那么运行该 :around 函数。(一般是父类的 :around)
2) 该主方法没有最想关的 :around 辅助方法,那么函数的执行权交还给主方法,主方法按正常情况运行,也即是,先运行 :before (如果有的话) ,再运行主方法,最后运行 :after (如果有的话)。
?
2.如果被调用的主方法(及父类的同名主方法)有 :before 辅助方法,那么它们按照最相关的最先运行的顺序依次执行,其中,不必调用 call-next-method 。
?
3.如果被调用的主方法(及其父类的同名主方法)有 :after 辅助方法,那么它们按照最相关的最后运行的顺序依次执行,其中,不必调用 call-next-method 。
?
4.如果主方法没有辅助方法,或者它的辅助方法全部执行完毕,那么执行该主方法。
?
OK,基本规则就这么多,我们先从 :before 辅助方法开始。
?
?
:before 辅助方法,无继承
?
无继承的 :before 辅助方法将在主方法之前执行,而且, :before 辅助方法执行完毕之后,调用会自动转给主方法,因此,不必调用 call-next-method 。
?
?
(defgeneric greet (people))(defclass person () ()) (defmethod greet ((people person)) (format t "greet ~%"))(defmethod greet :before ((people person)) (format t "greet :before ~%"))?
?
以下正是我们想要的执行结果:
?
?
(greet (make-instance 'person))
greet :before?
greet?
NIL
?
?
?
:before 辅助方法,带继承
?
这次,我们用一个 animal 类作为 person 的父类,调用 greet 方法。
?
如果一切如常的话,它们的调用顺序应该是 person 类的 greet 的 :before 辅助函数,然后是 animal 类的 greet 的 :before 辅助函数,然后是 person 的 greet 方法。
?
?
(defgeneric greet (people))(defclass animal () ()) (defmethod greet :before ((people animal)) (format t "animal's greet :before ~%"))(defclass person (animal) ()) (defmethod greet ((people person)) (format t "greet ~%"))(defmethod greet :before ((people person)) (format t "greet :before ~%"))
?
?
?执行结果:
?
?
(greet (make-instance 'person))
greet :before?
animal's greet :before?
greet?
NIL
?
?
OK,方法如我们所料般执行。
?
我们可以来讲讲 :after 辅助方法了。
?
?
:after 辅助方法,无继承
?
无继承的带 :after 的辅助函数,将在主方法之后执行。
?
?
(defgeneric greet (people))(defclass person () ()) (defmethod greet ((people person)) (format t "greet ~%")) (defmethod greet :after ((people person)) (format t "greet :after ~%"))
?
执行:
?
(greet (make-instance 'person))
greet?
greet :after?
NIL
(defgeneric greet (people))(defclass animal () ())(defmethod greet :after ((people animal)) (format t "animal's greet :after ~%"))(defclass person (animal) ()) (defmethod greet ((people person)) (format t "greet ~%")) (defmethod greet :after ((people person)) (format t "greet :after ~%"))?测试:
(defgeneric greet (people))(defclass person () ()) (defmethod greet ((people person)) (format t "greet ~%"))(defmethod greet :around ((people person)) (format t ":around ~%"))(defmethod greet :before ((people person)) (format t ":before ~%")) (defmethod greet :after ((people person)) (format t ":after ~%"))?执行试试:
(defgeneric greet (people))(defclass person () ()) (defmethod greet ((people person)) (format t "greet ~%"))(defmethod greet :around ((people person)) (format t ":around ~%") (call-next-method)) ; new add(defmethod greet :before ((people person)) (format t ":before ~%")) (defmethod greet :after ((people person)) (format t ":after ~%"))?测试:
(defgeneric greet (people))(defclass animal () ())(defmethod greet :around ((people animal)) (format t "animal's greet :around ~%") (call-next-method)) ; call person's greet :before(defclass person (animal) ())(defmethod greet ((people person)) (format t "greet ~%"))(defmethod greet :around ((people person)) (format t ":around ~%") (call-next-method)) ; call animal's greet :around(defmethod greet :before ((people person)) (format t ":before ~%"))(defmethod greet :after ((people person)) (format t ":after ~%"))
(defgeneric greet (people))(defclass animal () ())(defmethod greet :around ((people animal)) (format t "animal's greet :around ~%")) ; no (call-next-method) anymore(defclass person (animal) ()) (defmethod greet ((people person)) (format t "greet ~%"))(defmethod greet :around ((people person)) (format t ":around ~%") (call-next-method)) ; call animal's greet :around(defmethod greet :before ((people person)) (format t ":before ~%"))(defmethod greet :after ((people person)) (format t ":after ~%"))?
(defclass person () ()) (defmethod greet :around ((people person)) (format t ":around ~%"))?测试:
?
?
?
?
?
?
?
?
?
?
?
?
?
?
1 楼 zx371323 2012-03-06 GOOD!