Common Lisp 物件系統（CLOS）是一種面向物件程式設計設施，它是 ANSI Common Lisp 的一部份。CLOS 是強力的動態物件系統，在根本上不同於靜態語言，比如 C 或 Java 中的那種 OOP 設施。CLOS 受到更早期的 Lisp 物件系統，比如 MIT 和 Xerox 的啟發，然而它比二者要更加泛化。 歷史 CLOS 最初被提議作為一種附加件，首次出現在 1988 年發表的《》，和 1990 年出版的《》第二版（也叫做 CLtL2）中。在 1994 年，CLOS 被接受為 ANSI 標準 Common Lisp 的一部份，並且已經被適配入其他 Lisp 方言比如和 Emacs Lisp 之中 CLOS is a standard Multiple vendors supply CLOS CLOS or parts of it is being used to add objectorientation to other Lisp dialects such as EuLisp or Emacs Lisp p 110 of Veitch 1998。 特徵 CLOS 的基本建造塊是類、方法、泛化函式和類的例項。CLOS 提供了定義它們的宏：defclass、defmethod 和 defgeneric。例項透過方法 makeinstance 來建立。CLOS 不是基於原型語言，類必須聲明於物件可以例項化為這個類的成員之前。 類 類是槽的一個列表，它可以有多個超類，和一個特定的元類。槽（CJava 用語中的成員變數），可以由類（一個類的所有例項共享這個槽）或例項來分配。每個槽都有一個名字，而一個槽的值可以使用函式 slotvalue，透過這個名字來訪問。可以定義額外的特定泛化函式，來寫或讀這些槽的值。在 CLOS 類中的每個槽，都必須有一個唯一的名字。 如同多數動態語言中的 OO 系統那樣，CLOS 不強制封裝。任何槽都可以使用 slotvalue 函式，或透過（可選的自動生成的）訪問子方法來訪問。要透過 slotvalue 進行訪問，就要知道這個槽的名字。CL 程式設計者使用這個語言的包設施，來宣告哪些函式或資料結構意圖被匯出。 CLOS 允許多重繼承。在多重繼承中方法執行的預設次序不正確的時候，程式設計者可以透過指定方法組合的次序，來解決這種（類 D 同時繼承一個超類 A 的兩個子類 B 和 C，四者形成菱形，如果 A 的某一方法被 B 和 C 覆寫，D 該繼承二者中哪一個？）。在 CLOS 中已經解決了（圓是橢圓的長軸與短軸相等的特殊情況，故而是其子類，但圓不能繼承橢圓的使得其不再為圓的方法，比如單獨改變長軸或短軸）。而多數 OOP 設計模式，要麼消失，要麼在性質上更加簡單了 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。 CLOS 是動態的，意味著不只是內容，它的物件的 結構，也可以在執行時間修改。CLOS 支援現場（onthefly）變更類定義，即使正在考慮的這個類的例項已經存在；還有透過 changeclass 運算元，變更一個給定例項的類成員關係。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 STANDARDGENERICFUNCTION COMMONLISPUSERF 0 定義對 f integer t 的實現，這裡的 t 匹配所有型別 defmethod f x integer y 1 STANDARDMETHOD COMMONLISPUSERF INTEGER T 10018B1F03 f 1 20 1 定義對 f integer real 的實現 defmethod f x integer y real 2 STANDARDMETHOD COMMONLISPUSERF INTEGER REAL 1001A0BB83 f 1 20 分派發生在執行時間 2 方法組合 在 CLOS 中的分派還不同於多數 OO 語言： 給出一個實際引數列表，確定一個可應用的方法的列表。 這個列表依據它們的形式引數的特殊化者（specializer）的特殊性（specificity）來排序。 接著使用泛化函式所用的那個方法組合，將從這個列表選擇出的那些方法組合成一個有效方法。 接著用最初的實際引數呼叫這個有效方法。 這個分派機制工作在執行時間。增加或移除方法，將導致在執行時間變更有效方法（即使在以相同實際引數呼叫泛化函式的時候）。變更方法組合還導致不同的有效方法。 除了常規（主要）方法之外，還有before、after 和around 這些 輔助 方法。前兩個方法按照基於類層級的特定次序，分別先於或後於主要方法而呼叫。around 方法可能控制主要方法是否執行。此外，程式設計者可以指定沿著類層級的所有可能的主要方法，是都應當被呼叫，還是隻呼叫提供最接近匹配的那個方法。 標準方法組合 提供上述的主要、之前、之後和圍繞方法。還有具有其他方法型別的其他方法組合。可以定義新的（簡單和複雜二者）方法組合和方法型別。 元物件協議 在 ANSI Common Lisp 標準之外，有一個廣泛實現的對 CLOS 的擴充套件，叫做元物件協議（MOP）。MOP 定義到 CLOS 實現基礎支撐的標準介面，將類、槽描述、泛化函式和方法自身，當作元類的例項，並允許定義新的元類，和修改所有 CLOS 行為。CLOS MOP 的靈活性，預示了面向方面程式設計，它是由同一群工程師比如開發的。MOP 透過一組協議，定義了整個物件系統的行為。這些定義是依據 CLOS 定義的。因此有可能透過擴充套件或變更已提供的 CLOS 系統的功能，來建立新的物件系統。1991 年出版的圖書《》描述了 CLOS MOP 的使用和實現。 各種 Common Lisp 實現對元物件協議有稍微不同的支援。Closer 計劃致力於提供缺失的特徵。 來自更早的基於 Lisp 的物件系統的影響 Howard Cannon Flavors A nonhierarchical approach to objectoriented programming Symbolics Inc 1982（和它的後繼者 New Flavors），是 MIT Lisp 機器上的物件系統。Lisp 機器作業系統的很大部份和它的很多應用，使用了 Flavors 或 New Flavors。Flavors 介入了多重繼承和 mixin 和其他一些特徵 pg 46 of Thompson C W Ross K M Tennant H R and Saenz R M 1983 Building Usable MenuBased 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 4355。Flavors 幾乎廢止了，儘管存在針對 Common Lisp 實現。Flavors 使用訊息傳遞範型。New Flavors 介入了泛化函式。 ，是 Xerox D 的 LOOPS 的後繼者。CommonLoops 是針對 Common Lisp 的實現。叫做可移植 CommonLoops（PCL）的可移植實現，是第一個 CLOS 實現。PCL 被廣泛的移植了，並仍為很多 Common Lisp 實現提供 CLOS 實現的基礎。PCL 絕大部份以可移植的 Common Lisp 實現，而只有很少的系統依賴部份。 其他語言中的 CLOS 由於 CLOS 的能力和表達力，還有歷史上能獲得到 TinyCLOS，它是為用於 Scheme 而書寫的簡化的可移植的 CLOS 實現，故而類 CLOS 的基於 MOP 的物件系統，成為大多數 Lisp 方言實現的事實規範，還能在一些其他語言的 OOP 設施中找到它： COS，C 物件系統 COS the C Object System 。 Dylan Dynace，（很大程度上）CLOS 的 C 實現。 EIEIO，用於 Emacs Lisp。 ILOS，用在 ISLISP 中。 PyCLOS，為 Python 3 實現了 CLOS 風格的泛化函式 PyCLOS。 具有 CLOS 的 Scheme 實現： Chicken Scheme 使用 COOPS。 。 GNU Guile 使用 GOOPS。 MIT Scheme 使用 SOS。 Sagittarius。 。 Meroon，用 Scheme 編寫的物件系統。 R7RS CLOS，基於 Tiny CLOS 的具有語法糖的 R7RS Scheme 庫。 Swindle，用在 Racket 中。 Tiny CLOS，Gregor Kiczales 開發。 引用 延伸閱讀 參考文獻 Jo A Lawless and Molly M Miller Understanding CLOS the Common Lisp Object System 1991 Digital Press The Common Lisp Object System An Overview by 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 stepbystep 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 Chapter 7 Objects CategoryCommon Lisp CategoryLISP 程式語言 Category 面向物件的程式設計