【问题标题】:How to make the instances of a class using a metaclass inherit from a specific superclass如何使用元类使类的实例继承自特定的超类
【发布时间】:2019-07-26 14:57:10
【问题描述】:

我正在尝试为 common lisp 实现 json 序列化 API。为了实现这一点,我定义了一个名为json-class 的元类。这个元类定义了插槽选项:ignore,用于忽略对象的特定插槽。由于我使用 yason 进行序列化过程,因此我想将方法​​ yason:encode-slots 专门用于使用元类 json-class 的类的每个对象。我能想到的唯一方法是让所有对象从json-object 类型的json-class 实例化,它可用于专门化方法。 我试图复制的行为与 MOP 已经实现的行为相同,该行为包含在每个类中,使用 standard-class 生成 standard-object 类型的对象。

【问题讨论】:

    标签: lisp common-lisp clos mop


    【解决方案1】:

    使用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) ())
    

    专业化VALIDATE-SUPERCLASS(另见VALIDATE-SUPERCLASS explained)。

    (defmethod validate-superclass ((j json-class) (s standard-class)) t)
    

    然后定义基础json-object

    (defclass json-object () () (:metaclass json-class))
    

    例如:

    (class-of (make-instance 'json-object))
    #<JSON-CLASS SO::JSON-OBJECT>
    

    返回的对象是json-objectjson-class的实例,standard-class的子类。

    【讨论】:

    • 所以,如果我理解正确,如果我想创建一个具有json-class 属性的类,并且我希望它继承所有专门为json-object 设计的方法,我应该定义例如类作为(defclass person (json-object) () (:metaclass json-class)) 对吗?我还想使用ensure-class-using-class 方法自动将json-object 添加到direct-superclasses 列表中,但它对我来说并不明确。在类定义中保持明确是否被认为是好的设计?或者有没有更好的方法来声明这样一个类?
    • @MPaga:我认为应该有一种简单的方法来默认超类(毕竟,有standard-class 的实例。但我不知道它应该是什么。
    【解决方案2】:

    如果你查看SBCL的源代码,你会发现它在shared-initialize内部的直接超类列表中添加了standard-object

             (setq direct-superclasses
                   (or direct-superclasses
                       (list (if (funcallable-standard-class-p class)
                                 *the-class-funcallable-standard-object*
                                 *the-class-standard-object*))))
    
    

    如果您希望将一个类隐式添加到直接超类列表中,最好在shared-initializeinitialize-instance 上的:around 方法中执行此操作。

    另一种选择是将compute-class-precedence-list 专门化为,例如:

    (cons my-superclass (call-next-method))

    这就是An existing JSON MOP library 所做的。

    编辑:

    我认为用compute-class-precedence-list 添加超类是未定义的行为,尽管它通常有效。我相信最好的解决方案是为shared-initializeinitialize-instance 编写一个:around 方法,首先检查(使用subclassp)您的类是否已经在继承链中,如果没有,则添加它。

    【讨论】:

      猜你喜欢
      • 2013-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多