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.
How to make the instances of a class using a metaclass inherit from a specific superclass
475 Views Asked by MPaga At
2
There are 2 best solutions below
2
On
Use Closer to Mop:
(defpackage :so (:use :closer-common-lisp))
(in-package :so)
;; Define a metaclass named json-class.
;; It inherits from a standard-class
(defclass json-class (standard-class) ())
Specialize VALIDATE-SUPERCLASS (see also VALIDATE-SUPERCLASS explained).
(defmethod validate-superclass ((j json-class) (s standard-class)) t)
Then you define the base json-object.
(defclass json-object () () (:metaclass json-class))
For example:
(class-of (make-instance 'json-object))
#<JSON-CLASS SO::JSON-OBJECT>
The returned object is a json-object, an instance of json-class, a subclass of standard-class.
If you look through the source code of SBCL, you'll find that it adds
standard-objectto the list of direct superclasses inside ofshared-initialize:If you wish to implicitly add a class to the direct superclasses list, it may be best to do so in an
:aroundmethod onshared-initializeorinitialize-instance.Another option is to specializecompute-class-precedence-listto, 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-listto add superclasses is undefined behavior, though it usually works. I believe the best solution is to write an:aroundmethod for eithershared-initializeorinitialize-instancethat first checks (usingsubclassp) whether your class is already in the inheritance chain, then adds it if not.