Common Lisp對象系統
Common Lisp對象系統(CLOS)是一種面向對象編程設施,它是ANSI Common Lisp的一部份。CLOS是強力的動態對象系統,在根本上不同於靜態語言,比如C++或Java中的那種OOP設施。CLOS受到更早期的Lisp對象系統,比如MIT Flavors和Xerox CommonLoops的啟發,然而它比二者要更加泛化。
編程範型 | 面向對象 |
---|---|
實作者 | ANSI X3J13委員會 |
面市時間 | 1988年 |
實作語言 | Common Lisp |
操作系統 | 跨平台 |
網站 | Common Lisp HyperSpec, Chapter 7: Objects |
啟發語言 | |
MIT Flavors, Xerox CommonLoops | |
影響語言 | |
Dylan, Tiny CLOS[1], COOPS[2], STklos, Gauche |
歷史
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類中的每個槽,都必須有一個唯一的名字。
如同多數動態語言中的OO系統那樣,CLOS不強制封裝。任何槽都可以使用slot-value
函數,或通過(可選的自動生成的)訪問子方法來訪問。要通過slot-value
進行訪問,就要知道這個槽的名字。CL編程者使用這個語言的包設施,來聲明哪些函數或數據結構意圖被導出。
CLOS允許多重繼承。在多重繼承中方法執行的缺省次序不正確的時候,編程者可以通過指定方法組合的次序,來解決這種菱形繼承問題(類D同時繼承一個超類A的兩個子類B和C,四者形成菱形,如果A的某一方法被B和C覆寫,D該繼承二者中哪一個?)。在CLOS中已經解決了圓–橢圓問題(圓是橢圓的長軸與短軸相等的特殊情況,故而是其子類,但圓不能繼承橢圓的使得其不再為圓的方法,比如單獨改變長軸或短軸)。而多數OOP設計模式,要麼消失,要麼在性質上更加簡單了[5]。
CLOS是動態的,意味着不只是內容,它的對象的「結構」,也可以在運行時間修改。CLOS支持現場(on-the-fly)變更類定義,即使正在考慮的這個類的實例已經存在;還有通過change-class
算子,變更一個給定實例的類成員關係。CLOS還允許在運行時間增加、重新定義和移除方法。
多分派
CLOS是一個多分派系統,這意味着方法,可以依據它們所要求的任何或所有實際參數來指定。多數OO語言是單分派的,意味着方法只能依據第一個實際參數來指定。其他不常見特徵是方法不「屬於」類;類不為泛化函數或方法提供命名空間。方法是獨立於類而定義的,並且它們對類的槽沒有特殊的訪問(比如this
、self
或protected
)。
在CLOS中的方法被組織入泛化函數。泛化函數是像函數一樣可調用的一個對象,它關聯着有共享的名字和參數結構的方法的一個搜集,其中每個都特定於不同的實際參數。因為Common Lisp為結構和內建數據類型(數值、字符串、字符、符號等)提供了非CLOS類,CLOS分派也工作在這些非CLOS類之上。CLOS還支持分派在個體對象之上(eql特殊化者)。CLOS缺省的不支持分派於所有Common Lisp數據類型上,比如分派不工作於完全特殊化的數組類型,或通過deftype
介入的類型。然而多數Common Lisp實現,提供了元對象協議,它允許泛化函數提供特定於應用的特殊化和分派規則。例如採用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
方法組合
在CLOS中的分派還不同於多數OO語言:
- 給出一個實際參數列表,確定一個可應用的方法的列表。
- 這個列表依據它們的形式參數的特殊化者(specializer)的特殊性(specificity)來排序。
- 接着使用泛化函數所用的那個方法組合,將從這個列表選擇出的那些方法組合成一個有效方法。
- 接着用最初的實際參數調用這個有效方法。
這個分派機制工作在運行時間。增加或移除方法,將導致在運行時間變更有效方法(即使在以相同實際參數調用泛化函數的時候)。變更方法組合還導致不同的有效方法。
除了常規(「主要」)方法之外,還有:before
、:after
和:around
這些「輔助」方法。前兩個方法按照基於類層級的特定次序,分別先於或後於主要方法而調用。:around
方法可能控制主要方法是否執行。此外,編程者可以指定沿着類層級的所有可能的主要方法,是都應當被調用,還是只調用提供最接近匹配的那個方法。
「標準方法組合」提供上述的主要、之前、之後和圍繞方法。還有具有其他方法類型的其他方法組合。可以定義新的(簡單和複雜二者)方法組合和方法類型。
元對象協議
在ANSI Common Lisp標準之外,有一個廣泛實現的對CLOS的擴展,叫做元對象協議(MOP)。MOP定義到CLOS實現基礎支撐的標準接口,將類、槽描述、泛化函數和方法自身,當作元類的實例,並允許定義新的元類,和修改所有CLOS行為。CLOS MOP的靈活性,預示了面向方面編程,它是由同一群工程師比如Gregor Kiczales開發的。MOP通過一組協議,定義了整個對象系統的行為。這些定義是依據CLOS定義的。因此有可能通過擴展或變更已提供的CLOS系統的功能,來建立新的對象系統。1991年出版的圖書《元對象協議的藝術》描述了CLOS MOP的使用和實現[6]。
各種Common Lisp實現對元對象協議有稍微不同的支持。Closer計劃致力於提供缺失的特徵[7]。
來自更早的基於Lisp的對象系統的影響
Flavor[8](和它的後繼者New Flavors),是MIT Lisp機器上的對象系統。Lisp機器操作系統的很大部份和它的很多應用,使用了Flavors或New Flavors。Flavors介入了多重繼承和mixin和其他一些特徵[9]。Flavors幾乎廢止了,儘管存在針對Common Lisp實現。Flavors使用消息傳遞范型。New Flavors介入了泛化函數。
CommonLoops[10],是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方言實現的事實規範,還能在一些其他語言的OOP設施中找到它:
- COOPS,用在Chicken Scheme中[2]
- COS,C對象系統[11]
- Dylan
- Dynace,(很大程度上)CLOS的C實現[12]
- EIEIO,用於Emacs Lisp[13]
- Gauche,一個具有CLOS的Scheme[14]
- GOOPS,在GNU Guile中[15]
- ILOS,在ISLISP中
- Meroon,Scheme中的一個對象系統[16]
- PyCLOS,為Python 3實現了CLOS風格的泛化函數[17]
- Sagittarius,一個具有CLOS的Scheme[18]
- SOS,用於MIT Scheme[19]
- STklos,一個具有CLOS的Scheme[20]
- Swindle,在Racket中[21]
- Tiny CLOS,Gregor Kiczales開發[1]
- VCLOS for SKILL[22]
引用
- ^ 1.0 1.1 Tiny CLOS, developed by Gregor Kiczales. [2021-03-27]. (原始內容存檔於2008-12-11).
- ^ 2.0 2.1 COOPS. [2021-03-27]. (原始內容存檔於2020-07-25).
- ^ 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++.
- ^ The Art of the Metaobject Protocol, Chapters 5 and 6 in Hypertext. [2022-02-05]. (原始內容存檔於2021-04-06).
- ^ Closer Project: Closer to MOP. [2021-03-27]. (原始內容存檔於2010-06-12).
- ^ 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).
- ^ 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).
- ^ EIEIO. [2021-03-27]. (原始內容存檔於2021-01-13).
- ^ Gauche. [2021-03-27]. (原始內容存檔於2020-11-09).
- ^ GOOPS. [2021-03-27]. (原始內容存檔於2021-05-08).
- ^ Meroon. [2021-03-27]. (原始內容存檔於2016-01-22).
- ^ PyCLOS
- ^ Sagittarius. [2021-03-27]. (原始內容存檔於2020-05-03).
- ^ sos. [2021-06-13]. (原始內容存檔於2021-04-24).
- ^ STklos. [2022-05-11]. (原始內容存檔於2021-03-04).
- ^ Swindle. [2021-03-27]. (原始內容存檔於2016-12-23).
- ^ VCLOS, CLOS for Skill (PDF). [2021-03-27]. (原始內容 (PDF)存檔於2015-09-18).
延伸閱讀
- 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 (頁面存檔備份,存於網際網路檔案館)