stringtranslate.com

Общая объектная система Lisp

Стандартная комбинация методов в 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 . [1]

Функции

Основными строительными блоками 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 также отличается от большинства объектно-ориентированных языков:

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

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

Например,

; Объявите прототип общей структуры аргументов. ( defgeneric f ( x y ))   ; Определите реализацию для (f целое число y), где y соответствует всем типам. ( defmethod f (( x целое число ) y ) 1 )     ( ж 1 2.0 ) => 1    ; Определите реализацию для (f целочисленное действительное число). ( defmethod f (( x целое число ) ( y вещественное )) 2 )      ( f 1 2.0 ) => 2 ;Отправка изменена во время выполнения.     

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

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

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

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

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

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

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

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

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

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

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

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

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

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

дальнейшее чтение

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

  1. ^ «CLOS — это стандарт. CLOS поставляют несколько поставщиков. CLOS (или его части) используется для добавления объектной ориентации в другие диалекты Lisp, такие как EuLisp или Emacs Lisp». п. 110 Вейча 1998 г.
  2. ^ На слайдах «Шаблоны проектирования в динамических языках» Питер Норвиг представляет свои выводы о том, что 16 из 23 шаблонов проектирования, взятых из различных учебников, либо «невидимы, либо проще» в Dylan или Common Lisp, чем в C++.
  3. ^ Проект Closer: Ближе к MOP
  4. Денио, Лоран (12 марта 2010 г.). Объектная система C: использование C как объектно-ориентированного языка высокого уровня (PDF) . arXiv : 1003.2547 . CiteSeerX 10.1.1.763.7946 . Проверено 17 марта 2022 г. 
  5. ^ Объектно-ориентированное расширение Dynace для C
  6. ^ Ньютон, Джим; Родос, Кристоф (28 ноября 2008 г.). «Пользовательские специалисты в объектно-ориентированном Лиспе». Журнал универсальной информатики . 14 (20): 3370–3388. CiteSeerX 10.1.1.523.2413 . дои : 10.3217/jucs-014-20-3370 . S2CID  12032836 . Проверено 17 марта 2022 г. 
  7. ^ Tiny CLOS, разработанный Грегором Кицалесом.

Литература