我正在尝试为 common lisp 实现 json 序列化 API。为了实现这一点,我定义了一个名为json-class
. 这个元类定义了:ignore
用于忽略对象的特定槽的槽选项。由于我使用 yason 进行序列化过程,因此我想将该方法专门yason:encode-slots
用于使用 metaclass 的类的每个对象json-class
。我能想到的唯一方法是使所有对象从可用于专门化方法json-class
的类型实例化。json-object
我试图复制的行为与 MOP 已经实现的行为相同,该行为包含在每个类中,使用standard-class
生成类型的对象standard-object
。
问问题
231 次
2 回答
2
使用更接近拖把:
(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) ())
专门化VALIDATE-SUPERCLASS
(另请参阅VALIDATE-SUPERCLASS 解释)。
(defmethod validate-superclass ((j json-class) (s standard-class)) t)
然后定义 base json-object
。
(defclass json-object () () (:metaclass json-class))
例如:
(class-of (make-instance 'json-object))
#<JSON-CLASS SO::JSON-OBJECT>
返回的对象是 的json-object
一个实例json-class
、一个子类standard-class
。
于 2019-07-26T15:31:39.440 回答
1
如果您查看 SBCL 的源代码,您会发现它添加standard-object
到 内部的直接超类列表中shared-initialize
:
(setq direct-superclasses
(or direct-superclasses
(list (if (funcallable-standard-class-p class)
*the-class-funcallable-standard-object*
*the-class-standard-object*))))
如果您希望将一个类隐式添加到直接超类列表中,最好在or的:around
方法中执行此操作。shared-initialize
initialize-instance
另一种选择是专注compute-class-precedence-list
于,例如:
(cons my-superclass (call-next-method))
这就是现有的 JSON MOP 库所做的。
编辑:
我认为compute-class-precedence-list
添加超类是未定义的行为,尽管它通常有效。我相信最好的解决方案是编写一个:around
方法,或者shared-initialize
首先initialize-instance
检查(使用subclassp
)你的类是否已经在继承链中,如果没有,则添加它。
于 2020-07-28T17:41:49.030 回答