Wspólny system obiektów Lisp — Common Lisp Object System
Common Lisp Object System (CLOS) jest zakład dla programowania obiektowego , który jest częścią ANSI Common Lisp . CLOS to potężny system obiektów dynamicznych , który radykalnie różni się od funkcji OOP, które można znaleźć w bardziej statycznych językach, takich jak C++ lub Java . CLOS został zainspirowany wcześniejszymi systemami obiektów Lisp, takimi jak MIT Flavors i CommonLoops , chociaż jest bardziej ogólny niż każdy z nich. Pierwotnie zaproponowany jako dodatek, CLOS został zaadoptowany jako część standardu ANSI dla Common Lisp i został zaadaptowany do innych dialektów Lisp, takich jak EuLisp lub Emacs Lisp .
funkcje
Podstawowymi elementami składowymi CLOS są metody , klasy , instancje tych klas i funkcje generyczne . CLOS przewiduje określenie tych makr: defclass
, defmethod
, i defgeneric
. Instancje tworzone są za pomocą metody make-instance
.
Klasy mogą mieć wiele nadklas , listę slotów (zmienne członkowskie w języku C++/Java) i specjalną metaklasę . Sloty mogą być przydzielane według klasy (wszystkie instancje klasy współdzielą slot) lub według instancji. Każdy slot ma nazwę, a do wartości slotu można uzyskać dostęp za pomocą tej nazwy za pomocą funkcji slot-value
. Dodatkowo można zdefiniować specjalne funkcje ogólne do zapisu lub odczytu wartości slotów. Każdy slot w klasie CLOS musi mieć unikalną nazwę.
CLOS to system wielu wysyłek . Oznacza to, że metody mogą być wyspecjalizowane na dowolnym lub wszystkich wymaganych argumentach. Większość języków OO to języki typu single-dispatch, co oznacza, że metody specjalizują się tylko na pierwszym argumencie. Inną niezwykłą cechą jest to, że metody nie „należą” do klas; klasy nie zapewniają przestrzeni nazw dla ogólnych funkcji lub metod. Metody są definiowane oddzielnie od klas i nie mają specjalnego dostępu (np. „This”, „self” lub „protected”) do gniazd klas.
Metody w CLOS są pogrupowane w funkcje generyczne . Funkcja generyczna to obiekt, który można wywoływać jak funkcja i który kojarzy kolekcję metod ze wspólną nazwą i strukturą argumentów, z których każda specjalizuje się w różnych argumentach. Ponieważ Common Lisp zapewnia klasy inne niż CLOS dla struktur i wbudowanych typów danych (liczby, łańcuchy, znaki, symbole, ...), wysyłanie CLOS działa również z tymi klasami innymi niż CLOS. CLOS obsługuje również wysyłkę pojedynczych obiektów (specjaliści eql). CLOS domyślnie nie obsługuje wysyłania przez wszystkie typy danych Common Lisp (na przykład wysyłanie nie działa dla w pełni wyspecjalizowanych typów tablic lub typów wprowadzonych przez deftype
). Jednak większość implementacji Common Lisp zapewnia protokół metaobiektowy, który umożliwia ogólnym funkcjom zapewnianie specjalizacji i reguł wysyłania specyficznych dla aplikacji.
Wysyłka w CLOS różni się również od większości języków OO:
- Mając listę argumentów, ustalana jest lista możliwych do zastosowania metod.
- Ta lista jest posortowana zgodnie ze specyfiką ich specjalistów w zakresie parametrów.
- Wybrane metody z tej listy są następnie łączone w skuteczną metodę przy użyciu kombinacji metod używanej przez funkcję generyczną.
- Następnie wywoływana jest efektywna metoda z oryginalnymi argumentami.
Ten mechanizm wysyłania działa w czasie wykonywania. Dodanie lub usunięcie metod może zatem prowadzić do zmiany efektywnych metod (nawet jeśli funkcja ogólna jest wywoływana z tymi samymi argumentami) w czasie wykonywania. Zmiana kombinacji metod może również prowadzić do różnych skutecznych metod.
Na przykład,
; declare the common argument structure prototype
(defgeneric f (x y))
; define an implementation for (f integer t), where t matches all types
(defmethod f ((x integer) y) 1)
(f 1 2.0) => 1
; define an implementation for (f integer real)
(defmethod f ((x integer) (y real)) 2)
(f 1 2.0) => 2 ; dispatch changed at runtime
Podobnie jak systemy obiektowe w większości języków dynamicznych , CLOS nie wymusza enkapsulacji . Dostęp do dowolnego gniazda można uzyskać za pomocą slot-value
funkcji lub (opcjonalnie wygenerowanych automatycznie) metod dostępu . Aby uzyskać do niego dostęp przez slot-value
musisz znać nazwę gniazda. Programiści CL używają funkcji pakietu języka, aby zadeklarować, które funkcje lub struktury danych są przeznaczone do eksportu.
Oprócz normalnych ( „pierwotne”) metodami, tam są :before
, :after
, i :around
„pomocniczy” metody. Dwie poprzednie są wywoływane przed lub po metodzie podstawowej, w określonej kolejności na podstawie hierarchii klas. :around
Metoda może kontrolować, czy metoda pierwotna jest wykonywany w ogóle. Dodatkowo programista może określić, czy wszystkie możliwe metody podstawowe w hierarchii klas powinny być wywoływane, czy tylko ta, która zapewnia najbliższe dopasowanie.
Standardowa metoda łączonych zapewnia podstawową przed, po i około metody opisano powyżej. Istnieją inne kombinacje metod z innymi typami metod. Można zdefiniować nowe (zarówno proste, jak i złożone) kombinacje metod i typy metod.
CLOS umożliwia wielokrotne dziedziczenie . Gdy domyślna kolejność wykonywania metod w dziedziczeniu wielokrotnym nie jest poprawna, programista może rozwiązać problemy dziedziczenia diamentów , określając kolejność kombinacji metod.
CLOS jest dynamiczny, co oznacza, że nie tylko zawartość, ale także strukturę jego obiektów można modyfikować w czasie wykonywania. CLOS obsługuje zmianę definicji klas w locie (nawet jeśli instancje danej klasy już istnieją), a także zmianę przynależności do klasy danej instancji za pomocą change-class
operatora. CLOS umożliwia również dodawanie, przedefiniowanie i usuwanie metod w czasie wykonywania. Problem koło-elipsy jest łatwo rozwiązywany w CLOS, a większość wzorców projektowych OOP albo znika, albo jest jakościowo prostsza.
CLOS nie jest językiem prototypowym : klasy muszą być zdefiniowane przed utworzeniem instancji obiektów jako członków tej klasy.
Protokół metaobiektu
Poza standardem ANSI Common Lisp istnieje szeroko zaimplementowane rozszerzenie CLOS o nazwie Metaobject Protocol (MOP). MOP definiuje standardowy interfejs do podstaw implementacji CLOS, traktując klasy, opisy slotów, funkcje generyczne i same metody jako instancje metaklas i umożliwia definiowanie nowych metaklas i modyfikację wszystkich zachowań CLOS. Elastyczność CLOS MOP zapowiada programowanie aspektowe , które zostało później opracowane przez niektórych z tych samych inżynierów, takich jak Gregor Kiczales . MOP definiuje zachowanie całego systemu obiektowego za pomocą zestawu protokołów. Są one zdefiniowane w kategoriach CLOS. W ten sposób możliwe jest tworzenie nowych systemów obiektowych poprzez rozszerzenie lub zmianę dostarczonej funkcjonalności CLOS. Książka The Art of the Metaobject Protocol opisuje użycie i implementację CLOS MOP.
Różne implementacje Common Lisp mają nieco inną obsługę protokołu Meta-Object. Projekt Closer ma na celu dostarczenie brakujących funkcji.
Wpływy starszych systemów obiektowych opartych na Lispie
Flavours (i jego następca New Flavors) był systemem obiektowym na MIT Lisp Machine . Duża część systemów operacyjnych Lisp Machine i wiele aplikacji do tego używa Smaków lub Nowych Smaków. Smaki wprowadziły między innymi wiele dziedziczenia i mixin . Smaki są w większości przestarzałe, chociaż istnieją implementacje dla Common Lisp. Flavours wykorzystywał paradygmat przekazywania wiadomości. Nowe Smaki wprowadziły funkcje ogólne.
CommonLoops był następcą LOOPS (od Xerox Interlisp -D). CommonLoops został zaimplementowany dla Common Lisp. Przenośna implementacja o nazwie Portable CommonLoops (PCL) była pierwszą implementacją CLOS. PCL jest szeroko przeniesiony i nadal stanowi podstawę dla implementacji CLOS kilku implementacji Common Lisp . PCL jest zaimplementowany głównie w przenośnym Common Lisp z tylko kilkoma częściami zależnymi od systemu.
CLOS w innych językach programowania
Ze względu na moc i ekspresywność CLOS, a także historyczną dostępność TinyCLOS (uproszczona przenośna implementacja CLOS napisana przez Gregora Kiczalesa do użytku z Scheme), systemy obiektowe oparte na MOP typu CLOS stały się de facto normą w większości Lisp implementacje dialektów, a także odnajdywanie ich w obiektach OOP innych języków :
- COS, system obiektów C
- Dylan
- Dynace, (w dużej mierze) implementacja CLOS w C
- EIEIO dla Emacs Lisp
- Gauche , Schemat z CLOS
- GOOPS w GNU Guile
- Ilos w ISLISP
- Meroon , system obiektowy w schemacie
- Strzelec , schemat z CLOS
- ScmObj , dla schematu
- SOS dla programu MIT
- STklos , schemat z CLOS
- Oszustwo w rakiecie
- COOPS w schemacie kurczaka
- VCLOS dla umiejętności
- Tiny-CLOS
Bibliografia
- „ CommonLoops: łączenie języka Lisp i programowania obiektowego ”, autor: Daniel G. Bobrow, Kenneth Kahn, Gregor Kiczales, Larry Masinter, Mark Stefik, Frank Zdybel. 1986, Portland, Oregon, Stany Zjednoczone. Strony 17–29 konferencji nt. Języki i aplikacje systemów programowania obiektowego , ISSN 0362-1340.
- „Historia i opis CLOS”, autorstwa Jima Veitcha. Strony 107–158 Handbook of Programming Languages, tom IV: Functional and Logic Programming Languages , wyd. Peter H. Salus . 1998 (wydanie 1), Macmillan Technical Publishing; ISBN 1-57870-011-6 .Linki zewnętrzne
Literatura
- Sonya Keene , Programowanie zorientowane obiektowo w Common Lisp: A Programmer's Guide to CLOS , 1988, Addison-Wesley. ISBN 0-201-17589-4 .Linki zewnętrzne
- Gregor Kiczales , Jim des Rivieres i Daniel G. Bobrow , The Art of the Metaobject Protocol , 1991, MIT Press. ISBN 0-262-61074-4 .Linki zewnętrzne
- Jo A. Lawless i Molly M. Miller , Zrozumienie CLOS: Common Lisp Object System , 1991, Digital Press, ISBN 1-55558-064-5
- Andreas Paepcke , Programowanie obiektowe: perspektywa CLOS , 1993, The MIT Press. ISBN 0-262-16136-2
- System obiektów Common Lisp: przegląd autorstwa Richarda P. Gabriela i Lindy DeMichiel stanowi dobre wprowadzenie do motywacji definiowania klas za pomocą funkcji generycznych.
- Podstawy CLOS autorstwa Nicka Levine'a przedstawia krok po kroku wdrażanie koncepcji OO w CLOS i sposób ich wykorzystania. Jest przeznaczony dla każdego, kto ma podstawową wiedzę o Lispie lub schemacie.
- Common Lisp HyperSpec , Rozdział 7: Obiekty