gpt4 book ai didi

lisp - 如何将父类(super class)对象传递给子类构造函数?

转载 作者:太空宇宙 更新时间:2023-11-03 18:39:49 25 4
gpt4 key购买 nike

假设我有一个类 A 有几个槽:

(defclass a ()
((a-1 :initarg :a-1)
(a-2 :initarg :a-2)))

和继承自 A 的类 B:

(defclass b (a)
((b-1 :initarg :b-1)))

如果我想实例化 Bmake-instance 会为我提供插槽 :a-1, :a-2 :b-1

这是一个疯狂的想法:如果我想使用 A 的现有实例实例化 B 并且只填充插槽 b-1 怎么办? ?

附言。为什么有用:如果 A 实现了一些 B 直接继承的通用方法,而不添加任何新内容。在另一种方法中,将 A 的实例作为 B 中的一个插槽,我需要编写简单的方法包装器来调用该插槽上的这些方法。

我能想到的唯一方法是:在辅助构造函数中分解对象A并将相应的插槽传递给Bmake-instance,即:

(defun make-b (b-1 a-obj)
(with-slots (a-1 a-2) a-obj
(make-instance 'b :b-1 b-1 :a-1 a-1 :a-2 a-2)))

有更好的方法吗? (或者,这种方法可能会导致非常糟糕的设计,我应该完全避免使用它吗?)

最佳答案

我认为没有通用的解决方案。考虑:应该发生什么,例如,如果类 A 有一些槽,这些槽不是简单地从一些 :initarg 初始化的,而是说,在 initialize-实例 还是共享初始化

也就是说,只要你能控制所有涉及的类,你就可以尝试

  • 制定一个由A实现的协议(protocol),类似于

    (defgeneric initargs-for-copy (object)
    (:method-combination append)
    (:method append (object) nil))

    (defmethod initargs-for-copy append ((object a))
    (list :a-1 (slot-value object 'a-1) :a-2 (slot-value object 'a-2)))

    (defun make-b (b-1 a-obj)
    (apply #'make-instance 'b :b-1 b-1 (initargs-for-copy a-obj)))
  • 在运行时使用 MOP 提取插槽(这可能需要了解您所选择的 Lisp 实现,或者借助某些库的帮助,例如 closer-mop 可通过quicklisp )

    (defun list-init-args (object)
    (let* ((class (class-of object))
    (slots (closer-mop:class-slots class)))
    (loop
    for slot in slots
    for name = (closer-mop:slot-definition-name slot)
    for keyword = (closer-mop:slot-definition-initargs slot)
    when (and keyword (slot-boundp object name))
    nconc (list (car keyword) (slot-value object name)))))

    (defun make-b (b-1 a-obj)
    (apply #'make-instance 'b :b-1 b-1 (list-init-args a-obj)))
  • 使用 change-classA 实例转换为 B 实例破坏性地。

无论如何:我不确定您的用例是否真的需要继承。组合方法在这里(从设计的角度来看)似乎更加清晰。除了让 B 通过 A 继承一些通用方法实现: B 的实例真的被认为是 A 的适当实例> 在您的实际应用程序中(即是否存在 is-a? 关系)?或者您只是想避免必须在此处提供包装器?

关于lisp - 如何将父类(super class)对象传递给子类构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35175395/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com