跳至內容

Common Lisp對象系統

本頁使用了標題或全文手工轉換
維基百科,自由的百科全書
Common Lisp對象系統
編程範型物件導向
實作者ANSI X3J13英語X3J13委員會
釋出時間1988年,​36年前​(1988
目前版本從屬於ANSI Common Lisp1994年,​31年前​(1994
實作語言Common Lisp
作業系統跨平台
網站Common Lisp HyperSpec, Chapter 7: Objects
受影響於
MIT Flavors英語Flavors (programming language), Xerox CommonLoops英語CommonLoops
影響語言
Dylan, Tiny CLOS[1], COOPS[2], STklos英語STklos, Gauche英語Gauche (Scheme implementation)

Common Lisp對象系統CLOS)是一種物件導向程式設計設施,它是ANSI Common Lisp的一部份。CLOS是強力的動態對象系統,在根本上不同於靜態語言,比如C++Java中的那種OOP設施。CLOS受到更早期的Lisp對象系統,比如MIT Flavors英語Flavors (programming language)Xerox CommonLoops英語CommonLoops的啟發,然而它比二者要更加泛化。

歷史

[編輯]

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中的方法被組織入泛化函數。泛化函數是像函數一樣可呼叫的一個對象,它關聯着有共用的名字和參數結構的方法的一個搜集,其中每個都特定於不同的實際參數。CLOS方法定義中的特指符(specializer),包容Common Lisp中內建資料類型的類型指定符(specifier),非CLOS類比如整數、實數、字串、字元、符號、陣列等,有類型指定符integerrealstringcharactersymbolarray等,CLOS分派從而也工作在這些非CLOS類之上。CLOS還通過eql類型指定符支援分派在個體對象之上[6]。特指符不能是類型指定符列表比如(vector single-float)

多數Common Lisp實現,提供了元對象協定,它允許泛化函數提供特定於應用的特殊化英語Special case(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

方法組合

[編輯]
在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中可以定義出一些輔助方法,即在定義方法時於方法名字之附加上限定符(qualifier):before:after:around。不帶有限定符的方法是主要方法。在CLOS的泛化函數的多分派機制中,方法選擇與組合不同於多數物件導向語言[7]

  1. 給出一個實際參數列,確定出可應用的那些方法,按限定符分別形成各自列表。
  2. 諸列表依據它們的形式參數的特指符(specializer)的特殊性(specificity)來排序。
  3. 接着使用泛化函數所用的那種方法組合,將從諸列表選擇出的那些方法組合成一個有效方法。
  4. 接着用最初的實際參數呼叫這個有效方法。

標準方法組合形成的有效方法中諸方法的按如下階段執行:

  1. 如果有:around方法,則最特殊的:around方法最先執行。如果:around方法呼叫了call-next-method函數,進而在類層級中有下一個可以應用的:around方法,則執行這個方法;如果:around方法沒有呼叫了call-next-method函數,則終止後續執行階段。
  2. 所有:before方法類別為基層級按照越特殊越優先的次序依次執行。
  3. 最特殊的主要方法最先執行。如果主要方法呼叫了call-next-method函數,進而在類層級中有下一個可以應用的主要方法,則執行這個方法,否則通知發生了錯誤並中止後續執行階段。
  4. 所有:after方法類別為基層級按照越廣泛越優先的次序依次執行。

這種分派機制工作在執行時間,增加或移除方法,將導致在執行時間變更有效方法,即使是在以相同實際參數呼叫泛化函數的時候都會變更,而變更方法組合還可導致不同的有效方法。標準方法組合提供上述的主要、之前、之後和圍繞方法,還有具有其他方法類型的其他方法組合,也可以定義新的或簡單或複雜的方法組合和方法類型。

標準方法組合中的這些輔助方法[8],對應於面向方面編程中的建議英語Advice (programming)。對比於在方面英語Aspect (computer programming)中規定當其他的類的指定名稱方法被執行時觸發建議的點切入英語pointcut,CLOS的泛化函數直接在類層級中選擇同名方法並組合上它的輔助方法形成有效方法來主動執行。

元對象協定

[編輯]

在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]

來自更早的基於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實現的,而只有很少的系統依賴部份。

其他語言中的CLOS

[編輯]

由於CLOS的能力和表達力,還有歷史上能獲得到TinyCLOS,它是Gregor Kiczales英語Gregor Kiczales為用於Scheme而書寫的簡化的可移植的CLOS實現,故而類CLOS的基於MOP的對象系統,成為大多數Lisp方言實現的事實規範:

CLOS還能在一些其他語言的OOP設施中找到它:

  • COS,C對象系統[22]
  • Dylan
  • Dynace,(很大程度上)CLOS的C實現[23]
  • PyCLOS,為Python 3實現了CLOS風格的泛化函數[24]

註釋

[編輯]
  1. ^ 菱形繼承問題英語diamond problem:類D同時繼承一個超類A的兩個子類B和C,四者形成菱形,如果A的某一方法被B和C覆寫,D該繼承二者中哪一個?
  2. ^ 圓繼承橢圓問題英語Circle-ellipse problem:圓是橢圓的長軸與短軸相等的特殊情況,故而是其子類,但圓不能繼承橢圓的使得其不再為圓的方法,比如單獨改變長軸或短軸。

參照

[編輯]
  1. ^ 1.0 1.1 Tiny CLOS, developed by Gregor Kiczales. 
  2. ^ 2.0 2.1 COOPS is an object system for Scheme. 
  3. ^ 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). 
  4. ^ "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
  5. ^ 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++.
  6. ^ Type Specifier EQL. 
  7. ^ Method Selection and Combination. 
  8. ^ A Brief Guide to CLOS. 
  9. ^ The Art of the Metaobject Protocol, Chapters 5 and 6 in Hypertext. [2022-02-05]. (原始內容存檔於2021-04-06). 
  10. ^ 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. 
  11. ^ Howard Cannon, Flavors: A non-hierarchical approach to object-oriented programming頁面存檔備份,存於互聯網檔案館), Symbolics Inc., 1982
  12. ^ 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.
  13. ^ 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). 
  14. ^ Virgo is an R7RS CLOS library based on Tiny CLOS with syntax sugers. 
  15. ^ Gauche Users’ Reference — Object system. 
  16. ^ GOOPS. [2021-03-27]. (原始內容存檔於2021-05-08). 
  17. ^ sos. [2021-06-13]. (原始內容存檔於2021-04-24). 
  18. ^ Sagittarius Users' Reference — CLOS. 
  19. ^ STklos Object System. 
  20. ^ Swindle. [2021-03-27]. (原始內容存檔於2016-12-23). 
  21. ^ EIEIO. [2021-03-27]. (原始內容存檔於2021-01-13). 
  22. ^ 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頁面存檔備份,存於互聯網檔案館
  23. ^ Dynace Object Oriented Extension To C. [2021-03-27]. (原始內容存檔於2021-02-11). 
  24. ^ PyCLOS — CLOS-style generic functions with annotation based syntax. 

延伸閱讀

[編輯]
  • Jim Veitch. A History and Description of CLOS. Peter H. Salus英語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英語Gregor Kiczales, Jim des Rivieres, Daniel G. Bobrow英語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英語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英語Common Lisp HyperSpec, Chapter 7: Objects頁面存檔備份,存於互聯網檔案館