Jump to content

Программирование на основе прототипов

(Перенаправлено с прототипа )

Программирование на основе прототипов — это стиль объектно-ориентированного программирования , в котором повторное использование поведения (известное как наследование ) осуществляется посредством процесса повторного использования существующих объектов , которые служат прототипами . Эту модель также можно назвать прототипным , прототипно-ориентированным, бесклассовым или экземплярно-ориентированным программированием.

Программирование на основе прототипов использует обобщенные объекты процесса, которые затем можно клонировать и расширять. На примере фруктов объект «фрукт» будет представлять свойства и функциональность фруктов в целом. Объект «банан» будет клонирован из объекта «фрукт» и к нему будут добавлены общие свойства, характерные для бананов. Каждый отдельный объект «банан» будет клонирован из общего объекта «банан». Сравните с парадигмой, основанной на классах «фрукт» , где класс будет расширен классом «банан » .

Первыми языками программирования , основанными на прототипах, были Director aka Ani (на базе MacLisp ) (1976–1979), а одновременно, а не независимо, ThingLab (на основе Smalltalk ) (1977–1981), соответствующие докторские проекты Кеннета Майкла Кана в Массачусетский технологический институт и Алан Гамильтон Родились в Стэнфорде (но работали с Аланом Кеем в Xerox PARC). Борнинг ввел слово «прототип» в своей статье TOPLAS 1981 года. Первым языком программирования на основе прототипов с более чем одним разработчиком или пользователем, вероятно, был Yale T Scheme (1981–1984), хотя, как и в случае с Director и ThingLab, он изначально говорил только об объектах без классов. Языком, который сделал популярным название и понятие прототипов, был Self (1985–1995), разработанный Дэвидом Ангаром и Рэндаллом Смитом для исследования тем в области объектно-ориентированного языкового проектирования.

С конца 1990-х годов бесклассовая парадигма становится все более популярной. Некоторыми современными языками, ориентированными на прототипы, являются ( и другие реализации ECMAScript , такие как JScript и Flash ActionScript , 1.0), Lua , Cecil JavaScript NewtonScript , Io , Ioke , MOO , REBOL и AHK .

С 2010-х годов появилось новое поколение языков с чисто функциональными прототипами, которые сводят ООП к самой сути: Jsonnet динамический ленивый чисто функциональный язык со встроенной объектной системой прототипов, использующей миксинов наследование ; Nix — это динамический ленивый чистый функциональный язык, который создает эквивалентную объектную систему («расширения» Nix) всего за два коротких определения функций (плюс множество других удобных функций). Оба языка используются для определения крупных распределенных конфигураций программного обеспечения (Jsonnet напрямую вдохновлен GCL, языком конфигурации Google, с помощью которого Google определяет все свои развертывания, и имеет схожую семантику, хотя и с динамической привязкой переменных). С тех пор другие языки, такие как Gerbil Scheme, реализовали чисто функциональные системы отложенных прототипов, основанные на аналогичных принципах.

Проектирование и реализация

[ редактировать ]

Этимологически «прототип» означает «первая отливка» («отливка» в смысле изготовления). Прототип — это конкретная вещь, из которой путем копирования и модификации могут быть созданы другие объекты. Например, Международный Прототип Килограмма — это реальный реально существующий объект, из которого путем копирования можно создавать новые объекты-килограммы. Для сравнения, «класс» — это абстрактная вещь, которой могут принадлежать объекты. Например, все объекты-килограммы относятся к классу KilogramObject, который может быть подклассом MetricObject, и так далее.

Прототипическое наследование в JavaScript описано Дугласом Крокфордом как

Вы создаете объекты-прототипы, а затем… создаете новые экземпляры. Объекты в JavaScript изменяемы, поэтому мы можем дополнять новые экземпляры, добавляя им новые поля и методы. Затем они могут послужить прототипами для еще более новых объектов. Нам не нужны классы, чтобы создавать множество похожих объектов… Объекты наследуются от объектов. Что может быть более объектно-ориентированным, чем это? [1]

Сторонники программирования на основе прототипов утверждают, что оно побуждает программиста сосредоточиться на поведении некоторого набора примеров и только позже беспокоиться о классификации этих объектов в архетипические объекты, которые позже используются аналогично классам . [2] Многие системы, основанные на прототипах, поощряют изменение прототипов во время выполнения , тогда как лишь очень немногие объектно-ориентированные системы, основанные на классах (например, динамическая объектно-ориентированная система, Common Lisp , Dylan , Objective-C , Perl , Python , Ruby или Smalltalk ) позволяют изменять классы во время выполнения программы.

Почти все системы, основанные на прототипах, основаны на интерпретируемых и динамически типизированных языках. Однако системы, основанные на статически типизированных языках, технически осуществимы. Язык Omega обсуждается в разделе «Прототипное программирование». [3] является примером такой системы, хотя, согласно веб-сайту Omega, даже Omega не является исключительно статической, а, скорее, ее «компилятор может использовать статическую привязку там, где это возможно, и может повысить эффективность программы».

Строительство объекта

[ редактировать ]

В языках, основанных на прототипах, нет явных классов. Объекты наследуются напрямую от других объектов через свойство прототипа. Свойство прототипа называется prototype в Self и JavaScript или proto в Ио . Существует два метода создания новых объектов: ex nihilo создание объекта («из ничего») или путем клонирования существующего объекта. Первый поддерживается посредством некоторой формы объектного литерала , объявлений, в которых объекты могут быть определены во время выполнения с помощью специального синтаксиса, такого как {...} и передается непосредственно в переменную. Хотя большинство систем поддерживают различные варианты клонирования, создание объектов ex nihilo не так распространено. [4]

В языках, основанных на классах, новый экземпляр создается с помощью функции-конструктора класса — специальной функции, которая резервирует блок памяти для членов объекта (свойств и методов) и возвращает ссылку на этот блок. необязательный набор аргументов В функцию может быть передан конструктора, которые обычно хранятся в свойствах. Полученный экземпляр унаследует все методы и свойства, определенные в классе, который действует как своего рода шаблон, на основе которого можно создавать объекты одинакового типа.

Системы, поддерживающие создание объектов ex nihilo, позволяют создавать новые объекты с нуля без клонирования существующего прототипа. Такие системы предоставляют специальный синтаксис для указания свойств и поведения новых объектов без ссылки на существующие объекты. Во многих языках прототипов существует корневой объект, часто называемый Object , который устанавливается в качестве прототипа по умолчанию для всех других объектов, созданных во время выполнения, и который содержит часто необходимые методы, такие как toString() функция, возвращающая описание объекта в виде строки. Одним из полезных аспектов создания объекта ex nihilo является обеспечение того, чтобы имена слотов (свойств и методов) нового объекта не конфликтовали в пространстве имен верхнего уровня с объектом Object . (В языке JavaScript это можно сделать, используя нулевой прототип, т.е. Object.create(null).)

Клонирование относится к процессу, при котором новый объект создается путем копирования поведения существующего объекта (его прототипа). Тогда новый объект будет обладать всеми качествами оригинала. С этого момента новый объект можно изменить. В некоторых системах результирующий дочерний объект сохраняет явную связь (посредством делегирования или сходства ) со своим прототипом, а изменения в прототипе приводят к тому, что соответствующие изменения становятся очевидными в его клоне. Другие системы, такие как Forth -подобный язык программирования Kevo , не распространяют изменения из прототипа таким образом, а вместо этого следуют более конкатенативной модели, где изменения в клонированных объектах не распространяются автоматически между потомками. [2]

// Example of true prototypal inheritance style in JavaScript.// Object creation using the literal object notation {}.const foo = { name: "foo", one: 1, two: 2 };// Another object.const bar = { two: "two", three: 3 };// Object.setPrototypeOf() is a method introduced in ECMAScript 2015.// For the sake of simplicity, let us pretend that the following// line works regardless of the engine used:Object.setPrototypeOf(bar, foo); // foo is now the prototype of bar.// If we try to access foo's properties from bar from now on, // we'll succeed. bar.one; // Resolves to 1.// The child object's properties are also accessible.bar.three; // Resolves to 3.// Own properties shadow prototype properties.bar.two; // Resolves to "two".bar.name; // Unaffected, resolves to "foo".foo.name; // Resolves to "foo".

Другой пример:

const foo = { one: 1, two: 2 };// bar.[[prototype]] = fooconst bar = Object.create(foo);bar.three = 3;bar.one; // 1bar.two; // 2bar.three; // 3

Делегация

[ редактировать ]

В языках на основе прототипов, использующих делегирование , среда выполнения языка способна отправлять правильный метод или находить нужную часть данных, просто следуя серии указателей делегирования (от объекта к его прототипу), пока не будет найдено совпадение. Все, что требуется для установления такого совместного поведения между объектами, — это указатель делегирования. В отличие от отношений между классом и экземпляром в объектно-ориентированных языках, основанных на классах, отношения между прототипом и его ответвлениями не требуют, чтобы дочерний объект имел память или структурное сходство с прототипом за пределами этой связи. Таким образом, дочерний объект может продолжать модифицироваться и дополняться с течением времени без изменения структуры связанного с ним прототипа, как в системах на основе классов. Также важно отметить, что можно добавлять или изменять не только данные, но и методы. По этой причине в некоторых языках, основанных на прототипах, данные и методы называются «слотами» или «членами». [ нужна ссылка ]

Конкатенация

[ редактировать ]

При конкатенативном прототипировании — подходе, реализуемом языком программирования Kevo — нет видимых указателей или ссылок на исходный прототип, из которого клонируется объект. Объект-прототип (родительский) копируется, а не связывается с ним, и делегирование отсутствует. В результате изменения прототипа не отразятся на клонированных объектах. [5] Кстати, язык программирования Cosmos достигает того же за счет использования постоянных структур данных . [6]

Основное концептуальное отличие этой схемы заключается в том, что изменения, внесенные в объект-прототип, не распространяются автоматически на клоны. Это можно рассматривать как преимущество или недостаток. (Тем не менее, Kevo предоставляет дополнительные примитивы для публикации изменений в наборах объектов на основе их сходства — так называемые семейные сходства или семейства клонов . механизм [5] — а не через таксономическое происхождение, как это типично для модели делегирования.) Также иногда утверждается, что прототипирование на основе делегирования имеет дополнительный недостаток, заключающийся в том, что изменения в дочернем объекте могут повлиять на последующую работу родительского объекта. Однако эта проблема не свойственна модели, основанной на делегировании, и не существует в языках, основанных на делегировании, таких как JavaScript, которые гарантируют, что изменения дочернего объекта всегда записываются в самом дочернем объекте, а не в родительском объекте (т. е. в дочернем объекте). value затеняет родительское значение, а не меняет родительское значение).

В упрощенных реализациях конкатенативное прототипирование будет иметь более быстрый поиск членов, чем прототипирование на основе делегирования (поскольку нет необходимости следовать цепочке родительских объектов), но, наоборот, будет использовать больше памяти (поскольку копируются все слоты, а не существует один слот, указывающий на родительский объект). Однако более сложные реализации могут избежать этой проблемы, хотя и требуется компромисс между скоростью и памятью. Например, системы с конкатенативным прототипированием могут использовать реализацию копирования при записи , чтобы обеспечить скрытое совместное использование данных — и Kevo действительно следует такому подходу. [7] И наоборот, системы с прототипированием на основе делегирования могут использовать кэширование для ускорения поиска данных.

Сторонники объектных моделей на основе классов, критикующие системы на основе прототипов, часто испытывают опасения, аналогичные опасениям, которые испытывают сторонники систем статических типов для языков программирования в отношении систем динамических типов (см. datatype ). Обычно такие проблемы связаны с корректностью , безопасностью , предсказуемостью , эффективностью и незнанием программиста.

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

Что касается эффективности, объявление классов упрощает многие оптимизации компилятора , которые позволяют разрабатывать эффективные методы и поиск переменных экземпляра. Что касается языка Self , много времени было потрачено на разработку, компиляцию и интерпретацию методов повышения производительности систем на основе прототипов по сравнению с системами на основе классов.

Распространенная критика языков, основанных на прототипах, заключается в том, что сообщество разработчиков программного обеспечения с ними незнакомо, несмотря на популярность и распространение JavaScript на рынке . Однако знания о системах, основанных на прототипах, увеличиваются с распространением фреймворков JavaScript и комплексным использованием JavaScript по мере развития Всемирной паутины (Web). [8] [ нужна ссылка ] ECMAScript 6 представил классы как синтаксический сахар вместо существующего в JavaScript наследования на основе прототипов, предоставляя альтернативный способ создания объектов и управления наследованием. [9]

Языки, поддерживающие программирование на основе прототипов

[ редактировать ]

См. также

[ редактировать ]
  1. ^ Крокфорд, Дуглас. «Прототипическое наследование в JavaScript» . Проверено 22 июня 2021 г.
  2. ^ Перейти обратно: а б Тайвалсаари, Антеро (1996). «Раздел 1.1». Классы против прототипов: некоторые философские и исторические наблюдения . стр. 44–50. CiteSeerX   10.1.1.56.4713 .
  3. ^ Блашек, Гюнтер. «Раздел 2.8». Omega: статически типизированные прототипы . п. 177.
  4. ^ Дони, Чистоф; Маленфан, Жак; Барду, Даниэль. «Раздел 1.2» (PDF) . Классификация языков программирования на основе прототипов . п. 17.
  5. ^ Перейти обратно: а б Антеро Тайвалсаар (2009). «Упрощение JavaScript с помощью наследования прототипов на основе конкатенации» (PDF) . Технологический университет Тампере. Архивировано из оригинала (PDF) 13 августа 2011 г. Проверено 11 марта 2015 г. Kevo реализовал объектную модель, основанную на чистой конкатенации, в которой новые объекты создавались путем копирования, а пространства имен всех объектов всегда были полностью автономными. … Более того, у Кево был внутренний механизм семейства клонов , который позволял отслеживать «генеалогию» изменений среди групп объектов, так что изменения отдельных объектов могли при необходимости распространяться на другие объекты.
  6. ^ «Объектно-ориентированное программирование» . Гитхаб . Проверено 4 сентября 2023 г.
  7. ^ Тайвалсаари, Антеро (1992). «Kevo, объектно-ориентированный язык программирования на основе прототипов, основанный на конкатенации и операциях модулей». Технический отчет Отчет LACIR 92-02 . Университет Виктории.
  8. ^ «Прототип объектно-ориентированного программирования с использованием JavaScript» . Список врозь . 26 апреля 2016 г. Проверено 21 октября 2018 г.
  9. ^ «Классы» . Справочник по JavaScript . Сеть разработчиков Mozilla . Проверено 9 февраля 2016 г.
  10. ^ Собственный язык сценариев. http://www.davidbrebner.com/?p=4 содержит несколько основных примеров использования.

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

[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 3e08b1c46eed6a651bba446645782ff4__1718644080
URL1:https://arc.ask3.ru/arc/aa/3e/f4/3e08b1c46eed6a651bba446645782ff4.html
Заголовок, (Title) документа по адресу, URL1:
Prototype-based programming - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)