Skip to content

Lisp - 对象

Common Lisp 具有一个强大且统一的对象系统,其中几乎所有事物都是一等对象,从简单的数字到复杂的数据结构,甚至函数。这种设计理念植根于 Lisp 的动态特性,即对象的类型是在运行时而非编译时确定的。本章将探讨 Lisp 对象的基本概念、它们的类型以及 Common Lisp 对象系统(CLOS)。

Lisp 是动态类型的,这意味着变量本身没有固定的类型;相反,它们所持有的值才具有类型。这带来了极大的灵活性。与此同时,Lisp 也是强类型的,这意味着它不会自动强制转换不兼容的类型(例如,在没有显式转换的情况下,你不能自动将数字和字符串相加)。任何对象的类型都可以在运行时检查。

;; A variable can hold different types of objects over its lifetime.
(let ((my-variable 42))
(print (type-of my-variable)) ;=> COMMON-LISP:INTEGER
(setf my-variable "Hello, Lisp!")
(print (type-of my-variable)) ;=> COMMON-LISP:SIMPLE-STRING
(setf my-variable '(1 2 3))
(print (type-of my-variable))) ;=> COMMON-LISP:CONS

Lisp 提供了一个丰富的内置数据类型层次结构。所有类型都继承自根类型 T。你可以使用 type-of 函数检查对象的类型,并使用谓词函数(按照惯例以 -p 或 p 结尾)检查其类型。

  • 标量类型:number(例如,integer、float、ratio)、character、symbol。
  • 集合类型:list(链表)、vector(一维数组)、array(多维)、hash-table、string。
  • 复合类型:structure(使用 defstruct 创建)、class-object(CLOS 类的实例)。
  • 特殊类型:function、pathname、stream。
(print (numberp 101)) ;=> T
(print (stringp "text")) ;=> T
(print (listp '(a b c))) ;=> T
(print (symbolp 'my-sym)) ;=> T
(print (stringp 42)) ;=> NIL

CLOS 是集成到 Common Lisp 中的面向对象编程(OOP)范式。它极其强大和灵活,超越了许多其他语言的 OOP 系统。CLOS 中的对象是使用 defclass 定义的类的实例。

  • 类:定义对象结构(槽)和行为的蓝图。使用 defclass 定义。
  • 实例:根据类定义使用 make-instance 创建的具体对象。
  • 槽:对象的属性或数据成员,类似于其他语言中的字段或属性。
  • 泛型函数:其行为由其参数的类或类型决定的函数。使用 defgeneric 定义。
  • 方法:针对特定参数类特化的泛型函数的实现。使用 defmethod 定义。这实现了多态性。
  • 多重继承:一个 CLOS 类可以从多个父类继承槽和方法,从而实现强大且可重用的代码模式。
  • 多重方法:与大多数面向对象编程语言中方法属于类并且仅基于宿主对象的类型进行分派不同,Lisp 的泛型函数可以根据多个参数的类型进行分派。
  • 统一系统:在 Lisp 中,几乎所有事物都是对象,提供了一致且可预测的环境。
  • 通过动态类型实现的灵活性:在运行时确定和检查类型的能力,允许代码具有高度适应性且富有表达力。
  • CLOS 的强大之处:对于复杂应用,CLOS 提供了一个最先进的 OOP 系统,其多重继承和多重方法等特性在许多主流语言中都无与伦比。

Lisp 对象系统是该语言强大能力的一个基石。它无缝融合了简单、内置的数据类型与一个复杂而世界一流的面向对象系统(CLOS)。理解所有数据都是有类型的对象,并且可以动态地与它们交互,是掌握 Lisp 表达能力的第一步。