I'm trying to implement json serialization API for common lisp. To achieve this I've defined a metaclass called json-class
. This metaclass defines the slot options :ignore
which are used to ignore specific slots of the object. Since I'm using yason for the serialization process, I wanted to specialize the method yason:encode-slots
to every object of classes that use the metaclass json-class
. The only way I can think of to achieve this, is to make all the objects instantiated from a json-class
of type json-object
which can be used to specialize the methods.
The behaviour that I'm trying to replicate is the same as the one already implemented by the MOP consisting in every class using the standard-class
producing an object of type standard-object
.
If you look through the source code of SBCL, you'll find that it adds standard-object
to the list of direct superclasses inside of shared-initialize
:
(setq direct-superclasses
(or direct-superclasses
(list (if (funcallable-standard-class-p class)
*the-class-funcallable-standard-object*
*the-class-standard-object*))))
If you wish to implicitly add a class to the direct superclasses list, it may be best to do so in an :around
method on shared-initialize
or initialize-instance
.
Another option is to specialize compute-class-precedence-list
to, for example:
(cons my-superclass (call-next-method))
This is what An existing JSON MOP library does.
EDIT:
I think messing with compute-class-precedence-list
to add superclasses is undefined behavior, though it usually works. I believe the best solution is to write an :around
method for either shared-initialize
or initialize-instance
that first checks (using subclassp
) whether your class is already in the inheritance chain, then adds it if not.