这种情况一次又一次地发生在我身上:我定义了类,却忘记了我希望它是可调用的,或者它是 Gtk 小部件类,因此需要说明它的元类。但是,一旦定义了它,SBCL 就不允许我更改元类(即使没有此类的实例)。例如,评估
(defclass foo ()
((slot-a)))
然后添加一个元类并重新评估:
(defclass foo ()
((slot-a))
(:metaclass gobject:gobject-class))
导致错误:
Cannot CHANGE-CLASS objects into CLASS metaobjects.
[Condition of type SB-PCL::METAOBJECT-INITIALIZATION-VIOLATION]
See also:
The Art of the Metaobject Protocol, CLASS [:initialization]
不幸的是,我没有《元对象协议(protocol)的艺术》的副本来检查它的内容。目前我能想到的唯一方法是重新启动 lisp,这可能会造成很大的破坏。
由于我很快意识到错误,我不介意通过删除它来完全避开定义的类。问题:
fmakunbound
对于功能。 最佳答案
Unfortunately I don't have a copy of The Art of the Metaobject Protocol to check what it says.
即使我推荐阅读这本书,你也可以在网上找到一些信息。参见示例
ENSURE-CLASS-USING-CLASS
.How to remove the class?
您可以使用
(SETF FIND-CLASS)
:(setf (find-class 'foo) nil)
或者,您可以使用花哨的粘液检查器。您调用
slime-inspect-defintion
同时指向类的名称。然后,您将看到名称。当你选择它时,你检查命名你的类的符号。然后,您可以看到如下内容:It names the class FOO [remove]
如果 FOO 只命名一个类,您可以使用更大的锤子:
(unintern 'foo)
If I have created instances of the class, is there a way to find them to nullify them and get them GCed?
不,只有 GC 具有全局 View ,并且出于实际原因,它通常不会保留关于谁引用特定对象(以及如何引用)的向后引用 1 .
除非您引入自己的(弱)哈希表来存储它们,否则没有类的所有实例的全局记录。但是,如果您保留了所有实例的记录,则可以
CHANGE-CLASS
他们。例如,您定义:(defclass garbage () ())
...您的对象中任何先前持有的引用都将被释放,并且 GC 有机会处理您的实例引用的对象。并且当另一个对象引用 'garbage 的实例时,您可以对其进行更新。您可以将旧类的实例更改为新类,而不是使用 'garbage(名称相同,但类对象不同)。
另请注意
CHANGE-CLASS
是一个通用函数。1 .实现可能会提供堆遍历器。参见示例 Heap walkers in Allegro CL .
关于common-lisp - 如何更改类的元类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38811931/