热门问题
时间线
聊天
视角

Common Lisp对象系统

来自维基百科,自由的百科全书

Remove ads

Common Lisp对象系统CLOS)是一种面向对象编程设施,它是ANSI Common Lisp的一部分。CLOS是强力的动态对象系统,在根本上不同于静态语言,比如C++Java中的那种OOP设施。CLOS受到更早期的Lisp对象系统,比如MIT Flavors英语Flavors (programming language)Xerox CommonLoops英语CommonLoops的启发,然而它比二者要更加泛化。

事实速览 编程范型, 实现者 ...
Remove ads

历史

CLOS最初被提议作为一种附加件,首次出现在1988年发表的《Common Lisp面向对象编程英语Object-Oriented Programming in Common Lisp[3],和1990年出版的《Common Lisp语言英语Common Lisp the Language》第二版(也叫做CLtL2)中。在1994年,CLOS被接受为ANSI标准Common Lisp的一部分,并且已经被适配入其他Lisp方言比如EuLisp英语EuLispEmacs Lisp之中[4]

特征

CLOS的基本建造块是方法泛化函数和类的实例。CLOS提供了定义它们的宏:defclassdefmethoddefgeneric。实例通过方法make-instance来创建。CLOS是基于类的编程语言,并非基于原型的编程语言,类必须声明于对象可以实例化为这个类的成员之前。

类是的一个列表,它可以有多个超类,和一个特定的元类。槽在C++/Java中被称为成员变量,它可以由类或实例来分配,类所分配的槽由其所有实例共享。每个槽都有一个名字,而一个槽的值可以使用函数slot-value,通过这个名字来访问。可以定义额外的特定泛化函数,来写或读这些槽的值。在CLOS类中的每个槽,都必须有一个唯一的名字。

如同多数动态语言中的对象系统那样,CLOS不强制封装,任何槽都可以使用slot-value函数,或通过可选的自动生成的访问子方法来访问。要通过slot-value进行访问,就要知道这个槽的名字,CL编程者使用这个语言的设施,来声明哪些函数或数据结构意图被导出。

CLOS允许多重继承。在多重继承中方法执行的缺省次序不正确的时候,编程者可以通过指定方法组合的次序,来解决这种菱形继承问题英语diamond problem[a]。在CLOS中已经解决了圆继承椭圆问题英语Circle-ellipse problem[b],而多数面向对象编程设计模式,要么消失,要么在性质上更加简单了[5]

CLOS是动态的,意味着不只是内容,它的对象的结构,也可以在运行时间修改。CLOS支持现场(on-the-fly)变更类定义,即使正在考虑的这个类的实例已经存在;还有通过change-class算子,变更一个给定实例的类成员关系。CLOS还允许在运行时间增加、重新定义和移除方法。

多分派

CLOS是一个多分派系统,这意味着方法,可以依据它们所要求的任何或所有实际参数来指定。多数面向对象语言是单分派的,意味着方法只能依据第一个实际参数来指定。方法不从属于类,类不为泛化函数或方法提供命名空间。方法是独立于类而定义的,并且它们对类的槽没有特殊的访问,CLOS不设立其他面向对象语言中常见的thisselfprotected

在CLOS中的方法被组织入泛化函数。泛化函数是像函数一样可调用的一个对象,它关联着有共享的名字和参数结构的方法的一个搜集,其中每个都特定于不同的实际参数。Common Lisp为结构和内建数据类型,比如数值、字符串、字符、符号等,提供了非CLOS类,CLOS分派也工作在这些非CLOS类之上。CLOS还支持分派在个体对象之上(eql特指符[6])。CLOS缺省的不支持分派于所有Common Lisp数据类型上,比如分派不工作于完全特殊化的数组类型,或通过deftype介入的类型。然而多数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
Remove ads

方法组合

Thumb
在ANSI common lisp中的标准方法组合,这里色泽最浅的是类C,类B是类C的超类,色泽最深的类A是类B的超类。合成有效方法的各个方法的最大可能执行次序是:
①类C的:around方法、类B的:around方法、类A的:around方法,
②类C的:before方法、类B的:before方法、类A的:before方法,
③类C的主要方法、类B的主要方法、类A的主要方法,
④类A的:after方法、类B的:after方法、类C的:after方法。

在CLOS中可以定义出一些辅助方法,即在定义方法时于方法名字之附加上限定符:before:after:around。不带有限定符的方法是主要方法,:before:after方法按照基于类层级的特定次序,分别先于或后于主要方法而调用。:around方法可能控制主要方法是否执行。此外,编程者可以指定沿着类层级的所有可能的主要方法,是都应当被调用,还是只调用提供最接近匹配的那个方法。

在CLOS的泛化函数的多分派机制中,方法选择与组合不同于多数面向对象语言[7]

  1. 给出一个实际参数列表,确定出可应用的那些方法,按限定符(qualifier)分别形成各自列表。
  2. 诸列表依据它们的形式参数的特指符(specializer)的特殊性(specificity)来排序。
  3. 接着使用泛化函数所用的那种方法组合,将从诸列表选择出的那些方法组合成一个有效方法。
  4. 接着用最初的实际参数调用这个有效方法。

这种分派机制工作在运行时间,增加或移除方法,将导致在运行时间变更有效方法,即使是在以相同实际参数调用泛化函数的时候都会变更,而变更方法组合还可导致不同的有效方法。标准方法组合提供上述的主要、之前、之后和围绕方法,还有具有其他方法类型的其他方法组合,也可以定义新的或简单或复杂的方法组合和方法类型。

标准方法组合中的这些辅助方法[8],对应于面向方面编程中的建议英语Advice (programming)。对比于在方面英语Aspect (computer programming)中规定当其他的类的指定名称方法被执行时触发建议的点切入英语pointcut,CLOS的泛化函数直接在类层级中选择同名方法并组合上它的辅助方法形成有效方法来主动执行。

Remove ads

元对象协议

在ANSI Common Lisp标准之外,有一个广泛实现的对CLOS的扩展,叫做元对象协议(MOP)。MOP定义到CLOS实现基础支撑的标准接口,将类、槽描述、泛化函数和方法自身,当作元类的实例,并允许定义新的元类,和修改所有CLOS行为。CLOS MOP的灵活性,预示了面向方面编程,它是由同一群工程师比如Gregor Kiczales英语Gregor Kiczales开发的。

元对象协议通过一组协议,定义了整个对象系统的行为。这些定义是依据CLOS定义的,因此有可能通过扩展或变更已提供的CLOS系统的功能,来建立新的对象系统。1991年出版的图书《元对象协议的艺术英语The Art of the Metaobject Protocol》描述了CLOS MOP的使用和实现[9]。各种Common Lisp实现对MOP有稍微不同的支持。Closer计划致力于提供缺失的特征[10]

Remove ads

来自更早的基于Lisp的对象系统的影响

Flavor英语Flavors (programming language)和它的后继者New Flavors[11],是MIT Lisp机器上的对象系统。Lisp机器操作系统的很大部分和它的很多应用,使用了Flavors或New Flavors。Flavors介入了多重继承mixin和其他一些特征[12]。Flavors使用消息传递范型,New Flavors介入了泛化函数。Flavors尽管存在针对Common Lisp实现,现已几乎废止了。

CommonLoops英语CommonLoops[13],是Xerox Interlisp英语Interlisp-D的LOOPS的后继者。CommonLoops是针对Common Lisp的实现。叫做可移植CommonLoops(PCL)的可移植实现,是第一个CLOS实现。PCL被广泛的移植了,并仍为很多Common Lisp实现提供CLOS实现的基础。PCL绝大部分是以可移植的Common Lisp实现的,而只有很少的系统依赖部分。

Remove ads

其他语言中的CLOS

由于CLOS的能力和表达力,还有历史上能获得到TinyCLOS,它是Gregor Kiczales英语Gregor Kiczales为用于Scheme而书写的简化的可移植的CLOS实现,故而类CLOS的基于MOP的对象系统,成为大多数Lisp方言实现的事实规范:

CLOS还能在一些其他语言的OOP设施中找到它:

  • COS,C对象系统[22]
  • Dylan
  • Dynace,(很大程度上)CLOS的C实现[23]
Remove ads

注释

引用

延伸阅读

参考文献

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads