热门问题
时间线
聊天
视角

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類,即integerrealstringcharactersymbol等,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