如何更改 class 的元数据class
How to change class's metaclass
这一次又一次发生在我身上:我定义了 class 并忘记了我想要它是可调用的或者它是 Gtk 小部件 class,因此它是 metaclass需要说明。但是,一旦它被定义,SBCL 就不允许我更改元 class(即使没有此 class 的实例)。例如,评估
(defclass foo ()
((slot-a)))
然后添加元class并重新评估:
(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]
不幸的是,我没有元对象协议的艺术的副本来检查它说的是什么。目前我唯一能想到的方法是重新启动 lisp,这可能会造成很大的破坏。
因为我很快就意识到错误,所以我不介意通过删除它来完全避开定义的 class。问题:
- 如果我已经创建了 class 的实例,有没有办法找到它们来使它们无效并让它们被 GC 处理?
- 如何删除class?类似
fmakunbound
的函数。
Unfortunately I don't have a copy of The Art of the Metaobject Protocol to check what it says.
尽管我推荐阅读这本书,但您可以在网上找到一些信息。例如参见 [=22=].
How to remove the class?
您可以使用 (SETF FIND-CLASS)
:
(setf (find-class 'foo) nil)
或者,您可以使用精美的粘液检查器。您在指向 class 的名称时调用 slime-inspect-defintion
。然后,你会看到这个名字。当你 select 它时,你检查命名你的 class 的符号。然后,你可以看到类似的东西:
It names the class FOO [remove]
如果 FOO 只命名一个 class,你可以使用更大的锤子:
(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 具有全局视图,出于实际原因,它通常不会保留关于谁引用特定对象(以及如何引用)的后向引用1。
class 的所有实例都没有全局记录,除非您引入自己的(弱)散列-table 来存储它们。但是,如果您保留了所有实例的记录,则可以 CHANGE-CLASS
它们。例如,您定义:
(defclass garbage () ())
...您的对象中之前持有的任何引用都将被释放,并且 GC 有机会处理您的实例引用的对象。当另一个对象引用“垃圾”实例时,您可以更新它。您可以将旧 classes 的实例更改为新的 class(名称相同,但 class 对象不同),而不是使用“垃圾”。
还要注意 CHANGE-CLASS
是一个通用函数。
1。实现可能会提供heap walkers。例如参见 [=25=].
这一次又一次发生在我身上:我定义了 class 并忘记了我想要它是可调用的或者它是 Gtk 小部件 class,因此它是 metaclass需要说明。但是,一旦它被定义,SBCL 就不允许我更改元 class(即使没有此 class 的实例)。例如,评估
(defclass foo ()
((slot-a)))
然后添加元class并重新评估:
(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]
不幸的是,我没有元对象协议的艺术的副本来检查它说的是什么。目前我唯一能想到的方法是重新启动 lisp,这可能会造成很大的破坏。
因为我很快就意识到错误,所以我不介意通过删除它来完全避开定义的 class。问题:
- 如果我已经创建了 class 的实例,有没有办法找到它们来使它们无效并让它们被 GC 处理?
- 如何删除class?类似
fmakunbound
的函数。
Unfortunately I don't have a copy of The Art of the Metaobject Protocol to check what it says.
尽管我推荐阅读这本书,但您可以在网上找到一些信息。例如参见 [=22=].
How to remove the class?
您可以使用 (SETF FIND-CLASS)
:
(setf (find-class 'foo) nil)
或者,您可以使用精美的粘液检查器。您在指向 class 的名称时调用 slime-inspect-defintion
。然后,你会看到这个名字。当你 select 它时,你检查命名你的 class 的符号。然后,你可以看到类似的东西:
It names the class FOO [remove]
如果 FOO 只命名一个 class,你可以使用更大的锤子:
(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 具有全局视图,出于实际原因,它通常不会保留关于谁引用特定对象(以及如何引用)的后向引用1。
class 的所有实例都没有全局记录,除非您引入自己的(弱)散列-table 来存储它们。但是,如果您保留了所有实例的记录,则可以 CHANGE-CLASS
它们。例如,您定义:
(defclass garbage () ())
...您的对象中之前持有的任何引用都将被释放,并且 GC 有机会处理您的实例引用的对象。当另一个对象引用“垃圾”实例时,您可以更新它。您可以将旧 classes 的实例更改为新的 class(名称相同,但 class 对象不同),而不是使用“垃圾”。
还要注意 CHANGE-CLASS
是一个通用函数。
1。实现可能会提供heap walkers。例如参见 [=25=].