2016-08-07 34 views
8

To zdarza mi się raz po raz: definiuję klasę i zapominam, że chciałem ją wypakować lub jest to, powiedzmy, klasa widgetu Gtk, dlatego trzeba podać metaklas. Jednak po zdefiniowaniu, SBCL nie pozwala mi zmienić metaklasy (nawet jeśli nie ma instancji tej klasy). Na przykład, ocenyJak zmienić metaklum klasy

(defclass foo() 
    ((slot-a))) 

a następnie dodanie metaklasa i ponownej oceny:

(defclass foo() 
    ((slot-a)) 
    (:metaclass gobject:gobject-class)) 

wyniki w błędzie:

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] 

Niestety nie ma kopii sztuki protokołu Metaobject, aby sprawdzić, co mówi. Na razie jedyny sposób, jaki mogłem wymyślić, to zrestartować seplenienie, co może być dość uciążliwe.

Ponieważ już niedługo zdaję sobie sprawę z błędu, nie mam nic przeciwko unikaniu całej klasy przez jej usunięcie. Pytania:

  • Jeśli utworzyłem instancje klasy, czy istnieje sposób na ich znalezienie, aby unieważnić je i uzyskać GCed?
  • Jak usunąć zajęcia? Coś jak fmakunbound dla funkcji.

Odpowiedz

9

Unfortunately I don't have a copy of The Art of the Metaobject Protocol to check what it says.

Choć polecam czytania książki można znaleźć informacje w Internecie. Zobacz na przykład ENSURE-CLASS-USING-CLASS.

How to remove the class?

Można użyć (SETF FIND-CLASS):

(setf (find-class 'foo) nil) 

Lub można użyć fantazyjne szlam inspektor. Dzwonisz pod numer slime-inspect-defintion, wskazując nazwę klasy. Wtedy zobaczysz nazwę. Po wybraniu sprawdzasz symbol nazwany klasą. Następnie można zobaczyć coś takiego:

It names the class FOO [remove] 

zrealizowane tylko Foo nazw klasie, można użyć większy młotek:

(unintern 'foo) 

If I have created instances of the class, is there a way to find them to nullify them and get them GCed?

Nie, tylko GC ma globalny widok, a ze względów praktycznych nie generuje on na ogół referencji wstecz dotyczących tego, kto odwołuje się do konkretnego obiektu (i jak). Nie ma globalnego zapisu wszystkich wystąpień klasy, chyba że wprowadzisz własny (słaby) tablicę mieszania, aby je zapisać. Ale jeśli zachowałeś zapis wszystkich swoich instancji, możesz je ustawić na CHANGE-CLASS. Na przykład, można zdefiniować:

(defclass garbage()()) 

... każdy wcześniej zajmował odniesienia w obiekcie zostanie wydany i GC ma możliwość dysponowania obiektami instancji gdzie przedstawieniu. A kiedy inny obiekt odwołuje się do instancji "śmieci", możesz go zaktualizować. Zamiast używać "śmieci", prawdopodobnie możesz zmienić wystąpienia starych klas na twoją nową klasę (nazwa jest taka sama, ale obiekt klasy jest inny). Należy również zauważyć, że CHANGE-CLASS jest funkcją ogólną.


. Wdrożenia mogą oferować robotów stertowych. Zobacz na przykład Heap walkers in Allegro CL.