Общая объектная система Lisp - Common Lisp Object System

Комбинация стандартных методов в ANSI common lisp

Объект Common Lisp системы (CLOS) представляет собой средство для объектно-ориентированного программирования , который является частью ANSI Common Lisp . CLOS - это мощная динамическая объектная система, которая радикально отличается от средств ООП, имеющихся в более статических языках, таких как C ++ или Java . CLOS был вдохновлен более ранними объектными системами Lisp, такими как MIT Flavors и CommonLoops , хотя он является более общим, чем любой другой. Первоначально предложенный как надстройка, CLOS был принят как часть стандарта ANSI для Common Lisp и был адаптирован к другим диалектам Lisp, таким как EuLisp или Emacs Lisp .

Функции

Основные строительные блоки CLOS - это методы , классы , экземпляры этих классов и универсальные функции . CLOS обеспечивает макросов для определения тех: defclass, defmethodи defgeneric. Экземпляры создаются с помощью метода make-instance.

Классы могут иметь несколько суперклассов , список слотов (переменные-члены на языке C ++ / Java) и специальный метакласс . Слоты могут быть распределены по классам (все экземпляры класса разделяют слот) или по экземплярам. У каждого слота есть имя, и значение слота можно получить по этому имени с помощью функции slot-value. Дополнительно могут быть определены специальные универсальные функции для записи или чтения значений слотов. Каждый слот в классе CLOS должен иметь уникальное имя.

CLOS - это система множественной диспетчеризации . Это означает, что методы могут быть специализированы на любом или всех их требуемых аргументах. Большинство объектно-ориентированных языков используют однократную отправку, что означает, что методы специализируются только на первом аргументе. Еще одна необычная особенность состоит в том, что методы не «принадлежат» классам; классы не предоставляют пространство имен для общих функций или методов. Методы определяются отдельно от классов, и у них нет специального доступа (например, «это», «себя» или «защищенный») к слотам классов.

Методы в CLOS сгруппированы в универсальные функции . Универсальная функция - это объект, который вызывается как функция и который связывает набор методов с общим именем и структурой аргументов, каждый из которых специализируется на разных аргументах. Поскольку Common Lisp предоставляет классы, отличные от CLOS, для структур и встроенных типов данных (числа, строки, символы, символы, ...), диспетчеризация CLOS работает также с этими классами, отличными от CLOS. CLOS также поддерживает отправку по отдельным объектам (специалистам eql). CLOS по умолчанию не поддерживает диспетчеризацию для всех типов данных Common Lisp (например, диспетчеризация не работает для полностью специализированных типов массивов или для типов, введенных с помощью deftype). Однако большинство реализаций Common Lisp предоставляют протокол метаобъектов, который позволяет универсальным функциям обеспечивать специфическую специализацию приложения и правила диспетчеризации.

Отправка в CLOS также отличается от большинства языков OO:

  1. Учитывая список аргументов, определяется список применимых методов.
  2. Этот список отсортирован в соответствии со спецификой их специализаций параметров.
  3. Выбранные методы из этого списка затем объединяются в эффективный метод с использованием комбинации методов, используемой универсальной функцией.
  4. Затем вызывается эффективный метод с исходными аргументами.

Этот механизм отправки работает во время выполнения. Таким образом, добавление или удаление методов может привести к изменению эффективных методов (даже если универсальная функция вызывается с теми же аргументами) во время выполнения. Изменение комбинации методов также может привести к различным эффективным методам.

Например,

; 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

Как и системы объектно-ориентированного программирования в большинстве динамических языков , CLOS не обеспечивает инкапсуляцию . Доступ к любому слоту можно получить с помощью slot-valueфункции или (возможно, автоматически сгенерированных) методов доступа . Чтобы получить к нему доступ через, slot-valueвы должны знать название слота. Программисты на CL используют средства пакета языка, чтобы объявить, какие функции или структуры данных предназначены для экспорта.

Помимо обычных ( «первичных») методов, существует также :before, :afterи :around«вспомогательные» методы. Первые два вызываются до или после основного метода в определенном порядке, основанном на иерархии классов. :aroundМетод может контролировать ли основной метод выполняется на всех. Кроме того, программист может указать, следует ли вызывать все возможные основные методы в иерархии классов или только тот, который обеспечивает наиболее близкое соответствие.

Стандартный метод-Комбинация обеспечивает первичный, перед тем , объяснены выше после и вокруг методов. Существуют и другие комбинации методов с другими типами методов. Могут быть определены новые (как простые, так и сложные) комбинации методов и типы методов.

CLOS допускает множественное наследование . Если порядок по умолчанию, в котором методы выполняются при множественном наследовании, неверен, программист может решить проблемы алмазного наследования , указав порядок комбинаций методов.

CLOS является динамическим, что означает, что не только содержимое, но и структура его объектов может быть изменена во время выполнения. CLOS поддерживает изменение определений классов на лету (даже если экземпляры рассматриваемого класса уже существуют), а также изменение членства в классе данного экземпляра с помощью change-classоператора. CLOS также позволяет добавлять, переопределять и удалять методы во время выполнения. Проблема круга-эллипса легко решается в CLOS, и большинство шаблонов проектирования ООП либо исчезают, либо становятся качественно проще.

CLOS не является языком прототипов : классы должны быть определены до того, как объекты могут быть созданы как члены этого класса.

Протокол метаобъектов

Помимо стандарта ANSI Common Lisp, существует широко используемое расширение CLOS, называемое протоколом метаобъектов (MOP). MOP определяет стандартный интерфейс к основам реализации CLOS, рассматривая классы, описания слотов, общие функции и методы как экземпляры метаклассов , и позволяет определять новые метаклассы и изменять все поведение CLOS. Гибкость CLOS MOP предвосхищает аспектно-ориентированное программирование , которое позже было разработано некоторыми из тех же инженеров, например Грегором Кичалесом . MOP определяет поведение всей объектной системы с помощью набора протоколов. Они определены в терминах CLOS. Таким образом, можно создавать новые объектные системы, расширяя или изменяя предоставленную функциональность CLOS. Книга Искусство протокола метаобъектов описывает использование и реализацию CLOS MOP.

Различные реализации Common Lisp немного по-разному поддерживают протокол метаобъектов. Проект Closer призван предоставить недостающие функции.

Влияния старых объектных систем на основе Lisp

Flavors (и его преемник New Flavors) была объектной системой на MIT Lisp Machine . Большая часть операционных систем Lisp Machine и многие приложения для нее используют разновидности или новые разновидности. Помимо прочего, Flavors представили множественное наследование и миксины . Flavors в основном устарели, хотя реализации для Common Lisp существуют. Flavors использовали парадигму передачи сообщений. В New Flavors представлены общие функции.

CommonLoops был преемником LOOPS (от Xerox Interlisp -D). CommonLoops был реализован для Common Lisp. Переносимая реализация под названием Portable CommonLoops (PCL) была первой реализацией CLOS. PCL широко переносится и по-прежнему является основой для реализации CLOS нескольких реализаций Common Lisp . PCL реализован в основном на переносимом Common Lisp с несколькими частями, зависящими от системы.

CLOS на других языках программирования

Благодаря мощности и выразительности CLOS, а также исторической доступности TinyCLOS (упрощенная переносимая реализация CLOS, написанная Грегором Кичалесом для использования с Scheme), CLOS-подобные объектные системы на основе MOP стали де-факто нормой в большинстве Lisp. реализации диалекта, а также находят свое применение в средствах ООП некоторых других языков :

Рекомендации

  • « CommonLoops: объединение Лиспа и объектно-ориентированного программирования » Дэниела Г. Боброу, Кеннета Кана, Грегора Кичалеса, Ларри Масинтера, Марка Стефика, Фрэнка Здибеля. 1986 год, Портленд, Орегон, США. Страницы 17–29 конференции по языкам и приложениям систем объектно-ориентированного программирования , ISSN 0362-1340.
  • «История и описание CLOS» Джима Вейтча. Страницы 107–158 Справочника по языкам программирования, Том IV: Функциональные и логические языки программирования , изд. Питер Х. Салус . 1998 (1-е издание), Macmillan Technical Publishing; ISBN  1-57870-011-6

Литература