Wspólny system obiektów Lisp — Common Lisp Object System

Standardowa kombinacja metod w powszechnym lispie ANSI

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:

  1. Mając listę argumentów, ustalana jest lista możliwych do zastosowania metod.
  2. Ta lista jest posortowana zgodnie ze specyfiką ich specjalistów w zakresie parametrów.
  3. Wybrane metody z tej listy są następnie łączone w skuteczną metodę przy użyciu kombinacji metod używanej przez funkcję generyczną.
  4. 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-valuefunkcji lub (opcjonalnie wygenerowanych automatycznie) metod dostępu . Aby uzyskać do niego dostęp przez slot-valuemusisz 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. :aroundMetoda 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-classoperatora. 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 :

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