Common Lisp对象系统

编程范型 | 面向对象 |
---|---|
實作者 | ANSI X3J13委员会 |
发行时间 | 1988年 |
当前版本 | 从属于ANSI Common Lisp(1994年 ) |
實作語言 | Common Lisp |
操作系统 | 跨平台 |
網站 | Common Lisp HyperSpec, Chapter 7: Objects |
受影响于 | |
MIT Flavors, Xerox CommonLoops | |
影響語言 | |
Dylan, Tiny CLOS[1], COOPS[2], STklos, Gauche |
Common Lisp对象系统(CLOS)是一种面向对象编程设施,它是ANSI Common Lisp的一部份。CLOS是强力的动态对象系统,在根本上不同于静态语言,比如C++或Java中的那种OOP设施。CLOS受到更早期的Lisp对象系统,比如MIT Flavors和Xerox CommonLoops的启发,然而它比二者要更加泛化。
历史
[编辑]CLOS最初被提议作为一种附加件,首次出现在1988年发表的《Common Lisp面向对象编程》[3],和1990年出版的《Common Lisp语言》第二版(也叫做CLtL2)中。在1994年,CLOS被接受为ANSI标准Common Lisp的一部份,并且已经被适配入其他Lisp方言比如EuLisp和Emacs Lisp之中[4]。
特征
[编辑]CLOS的基本建造块是类、方法、泛化函数和类的实例。CLOS提供了定义它们的宏:defclass
、defmethod
和defgeneric
。实例通过方法make-instance
来创建。CLOS是基于类的编程语言,并非基于原型的编程语言,类必须声明于对象可以实例化为这个类的成员之前。
类
[编辑]类是槽的一个列表,它可以有多个超类,和一个特定的元类。槽在C++/Java中被称为成员变量,它可以由类或实例来分配,类所分配的槽由其所有实例共享。每个槽都有一个名字,而一个槽的值可以使用函数slot-value
,通过这个名字来访问。可以定义额外的特定泛化函数,来写或读这些槽的值。在CLOS类中的每个槽,都必须有一个唯一的名字。
如同多数动态语言中的对象系统那样,CLOS不强制封装,任何槽都可以使用slot-value
函数,或通过可选的自动生成的访问子方法来访问。要通过slot-value
进行访问,就要知道这个槽的名字,CL编程者使用这个语言的包设施,来声明哪些函数或数据结构意图被导出。
CLOS允许多重继承。在多重继承中方法执行的缺省次序不正确的时候,编程者可以通过指定方法组合的次序,来解决这种菱形继承问题[a]。在CLOS中已经解决了圆继承椭圆问题[b],而多数面向对象编程设计模式,要么消失,要么在性质上更加简单了[5]。
CLOS是动态的,意味着不只是内容,它的对象的结构,也可以在运行时间修改。CLOS支持现场(on-the-fly)变更类定义,即使正在考虑的这个类的实例已经存在;还有通过change-class
算子,变更一个给定实例的类成员关系。CLOS还允许在运行时间增加、重新定义和移除方法。
多分派
[编辑]CLOS是一个多分派系统,这意味着方法,可以依据它们所要求的任何或所有实际参数来指定。多数面向对象语言是单分派的,意味着方法只能依据第一个实际参数来指定。方法不从属于类,类不为泛化函数或方法提供命名空间。方法是独立于类而定义的,并且它们对类的槽没有特殊的访问,CLOS不设立其他面向对象语言中常见的this
、self
或protected
。
在CLOS中的方法被组织入泛化函数。泛化函数是像函数一样可调用的一个对象,它关联着有共享的名字和参数结构的方法的一个搜集,其中每个都特定于不同的实际参数。CLOS方法定义中的特指符(specializer),包容Common Lisp中内建数据类型的类型指定符(specifier),非CLOS类比如整数、实数、字符串、字符、符号、数组等,有类型指定符integer
、real
、string
、character
、symbol
、array
等,CLOS分派从而也工作在这些非CLOS类之上。CLOS还通过eql
类型指定符支持分派在个体对象之上[6]。特指符不能是类型指定符列表比如(vector single-float)
。
多数Common Lisp实现,提供了元对象协议,它允许泛化函数提供特定于应用的特殊化(specialization)和分派规则。下面的泛化函数的例子采用了SBCL来演示:
; 声明共同的实际参数结构原型
* (defgeneric f (x y))
#<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::F (0)>
; 定义对(f integer t)的实现,这里的t匹配所有类型
* (defmethod f ((x integer) y) 1)
#<STANDARD-METHOD COMMON-LISP-USER::F (INTEGER T) {10018B1F03}>
* (f 1 2.0)
1
; 定义对(f integer real)的实现
* (defmethod f ((x integer) (y real)) 2)
#<STANDARD-METHOD COMMON-LISP-USER::F (INTEGER REAL) {1001A0BB83}>
* (f 1 2.0) ; 分派发生在运行时间
2
方法组合
[编辑]
①类C的:around方法、类B的:around方法、类A的:around方法,
②类C的:before方法、类B的:before方法、类A的:before方法,
③类C的主要方法、类B的主要方法、类A的主要方法,
④类A的:after方法、类B的:after方法、类C的:after方法。
在CLOS中可以定义出一些辅助方法,即在定义方法时于方法名字之附加上限定符(qualifier):before
、:after
和:around
。不带有限定符的方法是主要方法。在CLOS的泛化函数的多分派机制中,方法选择与组合不同于多数面向对象语言[7]:
- 给出一个实际参数列表,确定出可应用的那些方法,按限定符分别形成各自列表。
- 诸列表依据它们的形式参数的特指符(specializer)的特殊性(specificity)来排序。
- 接着使用泛化函数所用的那种方法组合,将从诸列表选择出的那些方法组合成一个有效方法。
- 接着用最初的实际参数调用这个有效方法。
标准方法组合形成的有效方法中诸方法的按如下阶段执行:
- 如果有
:around
方法,则最特殊的:around
方法最先执行。如果:around
方法调用了call-next-method
函数,进而在类层级中有下一个可以应用的:around
方法,则执行这个方法;如果:around
方法没有调用了call-next-method
函数,则终止后续执行阶段。 - 所有
:before
方法基于类层级按照越特殊越优先的次序依次执行。 - 最特殊的主要方法最先执行。如果主要方法调用了
call-next-method
函数,进而在类层级中有下一个可以应用的主要方法,则执行这个方法,否则通知发生了错误并中止后续执行阶段。 - 所有
:after
方法基于类层级按照越广泛越优先的次序依次执行。
这种分派机制工作在运行时间,增加或移除方法,将导致在运行时间变更有效方法,即使是在以相同实际参数调用泛化函数的时候都会变更,而变更方法组合还可导致不同的有效方法。标准方法组合提供上述的主要、之前、之后和围绕方法,还有具有其他方法类型的其他方法组合,也可以定义新的或简单或复杂的方法组合和方法类型。
标准方法组合中的这些辅助方法[8],对应于面向方面编程中的建议。对比于在方面中规定当其他的类的指定名称方法被执行时触发建议的点切入,CLOS的泛化函数直接在类层级中选择同名方法并组合上它的辅助方法形成有效方法来主动执行。
元对象协议
[编辑]在ANSI Common Lisp标准之外,有一个广泛实现的对CLOS的扩展,叫做元对象协议(MOP)。MOP定义到CLOS实现基础支撑的标准接口,将类、槽描述、泛化函数和方法自身,当作元类的实例,并允许定义新的元类,和修改所有CLOS行为。CLOS MOP的灵活性,预示了面向方面编程,它是由同一群工程师比如Gregor Kiczales开发的。
元对象协议通过一组协议,定义了整个对象系统的行为。这些定义是依据CLOS定义的,因此有可能通过扩展或变更已提供的CLOS系统的功能,来建立新的对象系统。1991年出版的图书《元对象协议的艺术》描述了CLOS MOP的使用和实现[9]。各种Common Lisp实现对MOP有稍微不同的支持。Closer计划致力于提供缺失的特征[10]。
来自更早的基于Lisp的对象系统的影响
[编辑]Flavor和它的后继者New Flavors[11],是MIT Lisp机器上的对象系统。Lisp机器操作系统的很大部份和它的很多应用,使用了Flavors或New Flavors。Flavors介入了多重继承和mixin和其他一些特征[12]。Flavors使用消息传递范型,New Flavors介入了泛化函数。Flavors尽管存在针对Common Lisp实现,现已几乎废止了。
CommonLoops[13],是Xerox Interlisp-D的LOOPS的后继者。CommonLoops是针对Common Lisp的实现。叫做可移植CommonLoops(PCL)的可移植实现,是第一个CLOS实现。PCL被广泛的移植了,并仍为很多Common Lisp实现提供CLOS实现的基础。PCL绝大部份是以可移植的Common Lisp实现的,而只有很少的系统依赖部份。
其他语言中的CLOS
[编辑]由于CLOS的能力和表达力,还有历史上能获得到TinyCLOS,它是Gregor Kiczales为用于Scheme而书写的简化的可移植的CLOS实现,故而类CLOS的基于MOP的对象系统,成为大多数Lisp方言实现的事实规范:
CLOS还能在一些其他语言的OOP设施中找到它:
注释
[编辑]引用
[编辑]- ^ 1.0 1.1 Tiny CLOS, developed by Gregor Kiczales.
- ^ 2.0 2.1 COOPS is an object system for Scheme.
- ^ Sonya Keene. Object-Oriented Programming in Common Lisp: A Programmer's Guide to CLOS. Addison-Wesley. 1988 [2022-02-09]. ISBN 0-201-17589-4. (原始内容存档于2022-02-09).
- ^ "CLOS is a standard. Multiple vendors supply CLOS. CLOS (or parts of it) is being used to add object-orientation to other Lisp dialects such as EuLisp or Emacs Lisp." p. 110 of Veitch 1998
- ^ In the Design Patterns in Dynamic Languages (页面存档备份,存于互联网档案馆) slides, Peter Norvig presents his findings that 16 out of 23 design patterns taken from various textbooks are either "invisible or simpler" in Dylan or Common Lisp than in C++.
- ^ Type Specifier EQL.
- ^ Method Selection and Combination.
- ^ A Brief Guide to CLOS.
- ^ The Art of the Metaobject Protocol, Chapters 5 and 6 in Hypertext. [2022-02-05]. (原始内容存档于2021-04-06).
- ^ Closer to MOP is a compatibility layer that rectifies many of the absent or incorrect CLOS MOP features across a broad range of Common Lisp implementations.
- ^ Howard Cannon, Flavors: A non-hierarchical approach to object-oriented programming (页面存档备份,存于互联网档案馆), Symbolics Inc., 1982
- ^ pg 46 of Thompson, C. W., Ross, K. M., Tennant, H. R., and Saenz, R. M. 1983. "Building Usable Menu-Based Natural Language Interfaces To Databases". In Proceedings of the 9th international Conference on Very Large Data Bases (October 31 – November 2, 1983). M. Schkolnick and C. Thanos, Eds. Very Large Data Bases. Morgan Kaufmann Publishers, San Francisco, CA, 43–55.
- ^ Daniel G. Bobrow, Kenneth Kahn, Gregor Kiczales, Larry Masinter, Mark Stefik, Frank Zdybel. CommonLoops, Merging Lisp and Object-Oriented Programming. Portland, Oregon, United States. Pages 17–29 of the Conference on Object Oriented Programming Systems Languages and Applications. 1986 [2022-04-28]. ISSN 0362-1340. (原始内容存档于2022-04-28).
- ^ Virgo is an R7RS CLOS library based on Tiny CLOS with syntax sugers.
- ^ Gauche Users’ Reference — Object system.
- ^ GOOPS. [2021-03-27]. (原始内容存档于2021-05-08).
- ^ sos. [2021-06-13]. (原始内容存档于2021-04-24).
- ^ Sagittarius Users' Reference — CLOS.
- ^ STklos Object System.
- ^ Swindle. [2021-03-27]. (原始内容存档于2016-12-23).
- ^ EIEIO. [2021-03-27]. (原始内容存档于2021-01-13).
- ^ C Object System: a framework that brings C to the level of other high level programming languages and beyond. [2022-02-05]. (原始内容存档于2021-05-01).
COS, the C Object System (页面存档备份,存于互联网档案馆) - ^ Dynace Object Oriented Extension To C. [2021-03-27]. (原始内容存档于2021-02-11).
延伸阅读
[编辑]- Jim Veitch. A History and Description of CLOS. Peter H. Salus (编). Handbook of Programming Languages, Volume IV: Functional and Logic Programming Languages. Macmillan Technical Publishing. 1998 (1st edition): 107–158. ISBN 1-57870-011-6.
参考文献
[编辑]- Sonya Keene. Object-Oriented Programming in Common Lisp: A Programmer's Guide to CLOS (PDF). Addison-Wesley. 1988 [2022-02-05]. ISBN 0-201-17589-4. (原始内容 (PDF)存档于2022-05-06).
- Gregor Kiczales, Jim des Rivieres, Daniel G. Bobrow. The Art of the Metaobject Protocol (PDF). MIT Press. 1991 [2022-02-05]. ISBN 0-262-61074-4. (原始内容 (PDF)存档于2022-02-05).
- Jo A. Lawless and Molly M. Miller, Understanding CLOS: the Common Lisp Object System, 1991, Digital Press, ISBN 1-55558-064-5
- Andreas Paepcke. Object-Oriented Programming: the CLOS Perspective. The MIT Press. 1993 [2022-02-05]. ISBN 0-262-16136-2. (原始内容存档于2022-02-05).
- The Common Lisp Object System: An Overview (页面存档备份,存于互联网档案馆) by Richard P. Gabriel and Linda DeMichiel provides a good introduction to the motivation for defining classes by means of generic functions.
- Fundamentals of CLOS (页面存档备份,存于互联网档案馆) by Nick Levine provides a step-by-step exposure to the implementation of OO concepts in CLOS, and how to utilize them. It is intended for anybody with a basic knowledge of Lisp or Scheme.
- Common Lisp HyperSpec, Chapter 7: Objects (页面存档备份,存于互联网档案馆)