Common Lisp對象系統

Common Lisp對象系統（CLOS）是一種面向對象編程設施，它是ANSI Common Lisp的一部份。CLOS是強力的動態對象系統，在根本上不同於靜態語言，比如C++或Java中的那種OOP設施。CLOS受到更早期的Lisp對象系統，比如MIT Flavors和Xerox CommonLoops的啟發，然而它比二者要更加泛化。

**歷史**
CLOS最初被提議作為一種附加件，首次出現在1988年發表的《Object-Oriented Programming in Common Lisp》，和1990年出版的《Common Lisp the Language》第二版（也叫做CLtL2）中。在1994年，CLOS被接受為ANSI標準Common Lisp的一部份，並且已經被適配入其他Lisp方言比如EuLisp和Emacs Lisp之中。

**特徵**
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中已經解決了Circle-ellipse problem（圓是橢圓的長軸與短軸相等的特殊情況，故而是其子類，但圓不能繼承橢圓的使得其不再為圓的方法，比如單獨改變長軸或短軸）。而多數OOP設計模式，要麼消失，要麼在性質上更加簡單了。
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))
#
 定義對(f integer t)的實現，這裡的t匹配所有類型- (defmethod f ((x integer) y) 1)
#- (f 1 2.0)
1
 定義對(f integer real)的實現- (defmethod f ((x integer) (y real)) 2)
#- (f 1 2.0) ; 分派發生在運行時間
2

**方法組合**
在ANSI common lisp中的標準方法組合，這裡色澤最淺的是類A，類B是類A的子類，色澤最深的類C是類B的子類。合成有效方法的各個方法的執行次序是：①類A的:around方法、類B的:around方法、類C的:around方法，②類A的:before方法、類B的:before方法、類C的:before方法，③類A的主要方法、類B的主要方法、類C的主要方法，④類C的:after方法、類B的:after方法、類A的:after方法。
在CLOS中的分派還不同於多數OO語言：
# 給出一個實際參數列表，確定一個可應用的方法的列表。
# 這個列表依據它們的形式參數的特殊化者（specializer）的特殊性（specificity）來排序。
# 接著使用泛化函數所用的那個方法組合，將從這個列表選擇出的那些方法組合成一個有效方法。
# 接著用最初的實際參數調用這個有效方法。
這個分派機制工作在運行時間。增加或移除方法，將導致在運行時間變更有效方法（即使在以相同實際參數調用泛化函數的時候）。變更方法組合還導致不同的有效方法。
除了常規（“主要”）方法之外，還有:before、:after和:around這些“輔助”方法。前兩個方法按照基於類層級的特定次序，分別先於或後於主要方法而調用。:around方法可能控制主要方法是否執行。此外，編程者可以指定沿著類層級的所有可能的主要方法，是都應當被調用，還是隻調用提供最接近匹配的那個方法。
“標準方法組合”提供上述的主要、之前、之後和圍繞方法。還有具有其他方法類型的其他方法組合。可以定義新的（簡單和複雜二者）方法組合和方法類型。

**元對象協議**
在ANSI Common Lisp標準之外，有一個廣泛實現的對CLOS的擴展，叫做元對象協議（MOP）。MOP定義到CLOS實現基礎支撐的標準接口，將類、槽描述、泛化函數和方法自身，當作元類的實例，並允許定義新的元類，和修改所有CLOS行為。CLOS MOP的靈活性，預示了面向方面編程，它是由同一群工程師比如Gregor Kiczales開發的。MOP通過一組協議，定義了整個對象系統的行為。這些定義是依據CLOS定義的。因此有可能通過擴展或變更已提供的CLOS系統的功能，來建立新的對象系統。1991年出版的圖書《The Art of the Metaobject Protocol》描述了CLOS MOP的使用和實現。
各種Common Lisp實現對元對象協議有稍微不同的支持。Closer計劃致力於提供缺失的特徵。

**來自更早的基於Lisp的對象系統的影響**
（和它的後繼者New Flavors），是MIT Lisp機器上的對象系統。Lisp機器操作系統的很大部份和它的很多應用，使用了Flavors或New Flavors。Flavors介入了多重繼承和mixin和其他一些特徵。Flavors幾乎廢止了，儘管存在針對Common Lisp實現。Flavors使用消息傳遞範型。New Flavors介入了泛化函數。
，是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設施中找到它：- COS，C對象系統 COS, the C Object System date=20140620141819 。- Dylan- Dynace，（很大程度上）CLOS的C實現。
*EIEIO，用於Emacs Lisp。- ILOS，用在ISLISP中。- PyCLOS，為Python 3實現了CLOS風格的泛化函數。
*具有CLOS的Scheme實現：
**Chicken Scheme使用COOPS。
**Gauche。
**GNU Guile使用GOOPS。
**MIT Scheme使用SOS。
**Sagittarius。
**STklos。- Meroon，用Scheme編寫的對象系統。- R7RS CLOS，基於Tiny CLOS的具有語法糖的R7RS Scheme庫。- Swindle，用在Racket中。- Tiny CLOS，Gregor Kiczales開發。

**引用**

**延伸閱讀**

**參考文獻**
 archive-url=https://web.archive.org/web/20220506070546/https://doc.lagout.org/programmation/Lisp/Object-Oriented%20Programming%20in%20Common%20Lisp_%20A%20Programmer%27s%20Guide%20to%20CLOS%20%5BKeene%201989-01-11%5D.pdf- Jo A. Lawless and Molly M. Miller, Understanding CLOS: the Common Lisp Object System, 1991, Digital Press, 1-55558-064-5- archive-url=https://web.archive.org/web/20220205100127/https://vdoc.pub/documents/object-oriented-programming-the-clos-perspective-6cf6hnm5eg20-  The Common Lisp Object System: An Overview date=20210324061255  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 date=20140610114656  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 date=20210425155557