Common Lisp 中 struct 和 class 的区别

Difference between struct and class in Common Lisp

我对结构的理解是它有存储数据的槽,有类型,有 make-X 和槽访问函数,并且可以通过方法专门化(因为它有类型).

我对class的理解是它具有相同的多重继承。 this question 的最佳答案指出结构可以具有单一继承,并且 CLOS 的初始实现比结构 "much slower"。

根据人们谈论 CLOS 和结构的方式,我认为肯定还有一些其他差异,但我的琐碎 google 搜索毫无结果。所以我问:CLOS 和结构之间的实际区别是什么?

defstruct 在幕后为您做更多工作,例如:

  1. 自动定义插槽访问器
  2. 定义可读print-object方法

此外,结构槽访问速度更快(尽管差异可能无关紧要)。

底线是,除非您需要 MOPish 功能,否则您可以不用 defsrtuct

结构

Structures更原始。它们提供在编程语言中通常称为 record 的内容。它们是在 classes 之前发明的。 1984 年的 CLtL1(第一本描述 Common Lisp 的书)已经有了结构,后来又增加了一个称为 CLOS 的标准对象系统。结构提供

  • 简洁的定义宏DEFSTRUCT
  • 单继承
  • 快速插槽访问
  • 定义 reader 和 setf 插槽访问权限
  • 定义类型谓词
  • 定义构造函数
  • 定义一个复制函数
  • 打印表示:可以读取和打印结构
  • 以上函数可能是内联的

有用的补充:

  • 除了结构类型之外,DEFSTRUCT 还可以定义基于列表和向量的结构表示

限制:

  • 更改结构类型后,结构实例不会更新
  • 如果更改了结构类型,最好重新编译并重新运行更改的代码。也许重新启动程序。重新定义结构的效果在标准 Common Lisp 中未定义。
  • 很少自省:可移植的 Common Lisp 没有以简单的方式告诉我 super/sub-strucures 结构。可移植的 Common Lisp 没有告诉我结构的插槽。
  • 默认情况下不通过插槽名称访问插槽

扩展程序

  • 一些实现提供了更多的运行时间自省和一些 CLOS 函数中的一些集成

CLOS classes

CLOS 是在 mid/late 80 年代基于两个早期的对象系统(Flavors 和 LOOPS)发明的。它提供:

  • 一个定义宏DEFCLASS
  • 多重继承
  • 用于创建、初始化等的协议
  • CLOS 对象可以在 运行 时间根据 class 变化进行更改和更新(新插槽、重新定义的插槽、删除的插槽、更改的继承......)
  • CLOS 对象可以更改其 class 并在 运行 时间更新
  • 可以通过插槽名称访问

限制:

  • 无默认值printer/reader
  • DEFCLASS定义不是很简洁

扩展

  • 通过添加特定于实现的功能来加快插槽访问速度
  • 元对象协议提供了额外的功能和灵活性:内省和反射。有时只提供部分 MOP。
  • 用户提供的扩展可用,特别是对于支持 MOP 的实现

Common Lisp

在某些情况下,Common Lisp 标准并未说明应如何实现功能:结构、classes,甚至可能是其他东西。示例是流和条件。如果 Common Lisp 实现对这些使用 CLOS,这通常是一个好兆头(为了增加灵活性)。