我想取消定义一个班级及其所有方法,但经过对Googlore的彻底搜索后,我一直无法找到关于如何做到这一点的线索。
我正在使用Commmon Lisp的实现,称为CCL(Clozure CL)。
答案 0 :(得分:5)
这是一个相当有趣的问题。虽然,sds's answer指出,您可以使用(setf (find-class 'class-name) nil)
使(make-instance 'class-name)
之类的内容停止工作,但实际上并不会删除该类。例如,您可以将(find-class …)
的早期结果保存在其他地方:
CL-USER> (defclass foo () ())
#<STANDARD-CLASS FOO>
CL-USER> (defmethod show ((x foo))
(print "x is a foo"))
STYLE-WARNING: Implicitly creating new generic function SHOW.
#<STANDARD-METHOD SHOW (FOO) {1002BFD321}>
CL-USER> (defparameter *foo-class* (find-class 'foo))
*FOO-CLASS*
CL-USER> (show (make-instance 'foo))
"x is a foo"
"x is a foo"
CL-USER> (setf (find-class 'foo) nil)
NIL
CL-USER> (make-instance 'foo)
; Evaluation aborted on #<SIMPLE-ERROR "There is no class named ~ .. {1002FDBC61}>.
CL-USER> (make-instance *foo-class*)
#<#<STANDARD-CLASS FOO> {1003217F91}>
我不确定是否有任何方法可以从系统中删除一个类,并且不清楚它究竟是什么意思,因为它必须解决如何处理任何现有实例的问题该课程。
(setf find-class)
也不会删除任何专门用于该类的方法。继续刚开始的例子,因为我们仍然可以在类的实例上调用show
,我们仍然可以检索专门的方法:
CL-USER> (show (make-instance *foo-class*))
"x is a foo"
"x is a foo"
CL-USER> (find-method #'show '() (list *foo-class*))
#<STANDARD-METHOD SHOW ((CLASS #<STANDARD-CLASS FOO>)) {1003A7D081}>
但是,您可以使用REMOVE-METHOD
从通用函数中删除适用的方法CL-USER> (remove-method #'show (find-method #'show '() (list *foo-class*)))
#<STANDARD-GENERIC-FUNCTION SHOW (0)>
CL-USER> (show (make-instance *foo-class*))
; Evaluation aborted on #<SIMPLE-ERROR "~@<There is no applicable method for the generic function ~2I~_~S~ .. {1002EA5731}>.
在Common Lisp对象系统(CLOS)中,方法不属于类,所以说“[取消定义]类及其所有方法”是没有意义的。相反,CLOS具有泛型函数,程序员定义了专门化泛型函数的方法。如上面的示例所示,虽然可能没有可移植的方法来取消定义类,但您可以删除专门用于该类实例的方法,但您必须追踪它们的内容。有关更多信息,请查看:
本主题也在comp.lang.lisp上进行了讨论:
答案 1 :(得分:2)
只需使用find-class
:
(setf (find-class 'myclass) nil)
但是,这不会破坏类对象,也不会删除相应的方法。
完整过程需要unintern myclass
符号和类的插槽名称 - 但您可能在其他地方使用这些符号,所以要小心!
您还必须从您定义它们的通用函数中remove-method
。
简而言之,这是一个巨大的企业,当然不值得努力。
只需重新启动Lisp会话。
答案 2 :(得分:2)
这不是便携式的,而是像LispWorks这样的IDE:
使用类浏览器,列出没有继承的类的所有方法,选择方法,从方法菜单调用 undefine
< / LI>在编辑器中选择defclass
表单,在 definitions 菜单中调用 undefine
CCL IDE可能没有这些命令,但 SLIME + Emacs 可能有类似的东西。
答案 3 :(得分:0)
几个星期前,我发现自己正在删除我正在处理的软件包并重新加载lisp文件以获得相同的预期效果(虽然我同意它有点过分,因为你放弃了所有定义的东西在那个包裹下)。
假设您的类定义位于单独的包中(可能是该包的单独文件),只需切换到cl包然后删除包,重新加载,再次切换回包。一个例子(来自我的sbcl提示符):
TESTPACKAGE> (in-package :cl)
CL> (delete-package :testpackage)
CL> (load "testpackage.lisp")
CL> (in-package :testpackage)
TESTPACKAGE>
答案 4 :(得分:0)
我偶然发现了这个:
HyperSpec中的标准通用功能#'make-instances-obsolete
。
重新定义a时要特别注意它如何与#'defclass
相互作用
“标准课”。
还要查看#'fmakunbound
,#'unintern
,#'delete-package
和
(remove-method
(find-method #'<generic-function-symbol>
'(:before :after :<some-other-qualifier-you-may-be-interested-in>)
;; specializers are the classes or eq specializers
;; in method lambda lists
'(<first-specializer> <second-specializer-and-so-on>)))
最后一段代码接近Joshua Taylor's answer。