我正在编写一些方法来为各种元素发出HTML。每种方法都有相同的输出,但不一定需要相同的输入。
回复game-board
的方法也需要player
(因为每个玩家只看到自己的棋子)
(defmethod echo ((board game-board) (p player)) ... )
回应棋盘空间不需要更换每个玩家(该调度实际上是在game-board
方法中完成的,后来在空格上调用echo
。理想情况下,我能够做到
(defmethod echo ((space board-space)) ... )
(defmethod echo ((space empty-space)) ... )
我也可以想到,我后来遇到的对象需要了解的不仅仅是玩家才能正确展示自己。既然已经有专门针对相同泛型的方法,那么会产生错误
The generic function #<STANDARD-GENERIC-FUNCTION ECHO (4)> takes 2 required arguments;
回过头来命名这些方法echo-space
,echo-board
等等似乎不太理想。
是否存在基于专门对象改变其他参数的规范方法?我应该做点什么吗
(defgeneric echo (thing &key player ...) ...)
或
(defgeneric echo (thing &rest other-args) ...)
?更一般地说,有人能指点我defgeneric
专门的教程吗? (我已经阅读了相关的PCL章节和some CLOS tutorials,但它们并没有涵盖我在这里要求的情况。)
答案 0 :(得分:5)
一般来说,如果两个函数的接口太不相同,则表明它们实际上不是同一操作的特化,也不应该具有相同的名称。如果你只想专注于可选/键参数,那么实现它的方法是使用一个普通的函数来调用一个泛型函数,并为缺少的参数提供默认值来专门研究。
我认为,Keene's book是CLOS最全面的指南。不幸的是,它似乎只能以书本形式提供。
答案 1 :(得分:3)
每当方法采用相同的参数但仅在数据类型上有所不同时,它会更容易。但是在通用函数和方法都使用相同名称(当然)但lambda列表变化很大的情况下,我个人倾向于使用&amp; key参数来明确我的意图,而不是使用&amp;可选参数。我认为它有助于以后的可读性。
尝试这样的事情(假装我们已经有类class -a和class-b):
(defgeneric foo (object &key &allow-other-keys)
(:documentation "The generic function. Here is where the docstring is defined."))
(defmethod foo ((object class-a) &key &allow-other-keys)
(print "Code goes here. We dispatched based on type Class A."))
(defmethod foo ((object class-b) &key (x 1) (y 2) &allow-other-keys)
(print "Code goes here. We dispatched based on type Class B. We have args X and Y."))
由于涉及“方法组合”,为了使调度逻辑“流”通过其可能的方法选择来使用,我们需要将方法定义看作有不兼容的lambda列表的链(即参数列表) )将打破这一链。这就是为什么方法定义中的&amp; key和&amp; allow-other-keys并不特别需要它们。将它们放在DEFGENERIC中,方法定义允许我们根据class-b调度方法定义。
免责声明:我自己就是一个Common Lisp新手,所以带上一粒盐吧!
答案 2 :(得分:0)
如何重构对象/类,以便每个要回显的对象在其自己的(和继承的)插槽中具有所有必需的属性?
这样,当你在对象上调用echo时,你不必将它们作为参数传递,因为你需要的东西已经存储在对象中了。