【发布时间】:2016-02-03 11:09:23
【问题描述】:
假设我的课程 A 有几个插槽:
(defclass a ()
((a-1 :initarg :a-1)
(a-2 :initarg :a-2)))
还有继承自A的类B:
(defclass b (a)
((b-1 :initarg :b-1)))
如果我想实例化B,make-instance 将为我提供插槽:a-1、:a-2 和:b-1。
这是一个疯狂的想法:如果我想使用 A 的现有实例实例化 B 并且只填充插槽 b-1,该怎么办?
PS。为什么有用:如果A 实现了B 直接继承的一些通用方法,而不添加任何新内容。在另一种方法中,使A 的实例成为B 中的一个槽,我需要编写简单的方法包装器来在该槽上调用这些方法。
我能想到的唯一方法:在辅助构造函数中分解对象A并将对应的插槽传递给make-instance for B,即:
(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 的实例并将其类更改为 B - 然后初始化添加的插槽。请注意,您确实需要摆脱“A 实现方法”的想法。这是 CLOS,其中类/槽和泛型函数/方法更加独立。
-
@RainerJoswig 改变班级的想法很有趣。但我不确定我是否完全理解你对类/槽和通用函数/方法之间的关系。我意识到它们是非常独立的实体。什么是“实现方法”思维的替代方案?
-
@mobiuseng 在 clos 中,并不是说“a 实现了方法 f”,而是“在泛型函数 f 上定义了一个专门用于 a 的方法”。当您将方法专门用于多个参数时,这是一个更明显的区别。
-
约书亚是对的。另外:“在泛型函数 f 上定义了一些方法,专门用于 a'。它可能不止一个。
-
@RainerJoswig 好的,我明白了。只是在这种特殊情况下,我只专注于一个参数,所以它看起来像“实现方法”。 CLOS的方式转移了很多焦点。
标签: lisp common-lisp clos