5

I would like to undefine a class and all of its methods but after a quite thorough search on Googlore I have been unable to find a clue about how to do this.

I am using an implementation of Commmon Lisp called CCL (Clozure CL).

4

4 回答 4

6

这是一个相当有趣的问题。虽然,正如sds 的回答所指出的那样,您可以使用停止工作之类的(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 上讨论​​过:

于 2013-09-04T17:09:26.600 回答
2

只需使用find-class

(setf (find-class 'myclass) nil)

但是,这不会破坏类对象,也不会删除相应的方法。

整个过程需要取消实习myclass符号和类的插槽名称 - 但您可能在其他地方使用这些符号,所以要小心!

您还必须remove-method从定义它们的通用函数中获取。

总之,这是一个巨大的企业,肯定不值得努力。

只需重新启动您的 Lisp 会话。

于 2013-09-04T16:57:01.960 回答
2

这不是可移植的,但在像 LispWorks 这样的 IDE 中:

  • 使用类浏览器,列出没有继承的类的所有方法,选择方法,从方法菜单调用undefine

  • 在编辑器中选择defclass表单,在定义菜单中调用undefine

CCL IDE 可能没有这些命令,但SLIME + Emacs可能有类似的东西。

于 2013-09-04T17:31:18.047 回答
1

我只是偶然发现了这个:

HyperSpec 中的标准泛型函数#'make-instances-obsolete。特别注意它#'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 的答案

于 2019-08-04T12:04:18.060 回答