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

Поделись знанием:
Перейти к: навигация, поиск
Парадигмы программирования
 • Императивная
(контрастирует с декларативной)
Процедурная
Структурная
Аспектно-ориентированная
Объектно-ориентированная
Агентно-ориентированная
Компонентно-ориентированная
Прототипно-ориентированная
Обобщённое программирование

 • Декларативная
(контрастирует с императивной)

Чистота языка
Чистота функции
Функциональная
В терминах Рефал-машины
Аппликативная
Комбинаторная
Бесточечная
(чистая конкатенативная)
Логическая
Ограничениями

 • Конкатенативная
 • Векторная[en]
 • Метапрограммирование

Языково-ориентированная
Предметно-ориентированная
Пользователями[en]
Автоматизация процесса программирования
Рефлексивность
Гомоиконность[en]

 • Связанные темы

Программирование в крупном и мелком масштабе[en]
Модульность
Полиморфизм
Продолжения и CPS
Параллелизм и конкурентность

 • Методы и алгоритмы

Автоматное
Динамическое
Потоков данных
Событийно-ориентированное
Реактивное
Сервис-ориентированное

Прототипное программирование — стиль объектно-ориентированного программирования, при котором отсутствует понятие класса, а наследование производится путём клонирования существующего экземпляра объекта — прототипа.

Каноническим примером прототип-ориентированного языка является язык Self. В дальнейшем этот стиль программирования начал обретать популярность и был положен в основу таких языков программирования, как JavaScript, Lua, Io, REBOL и др.





Сравнение с класс-ориентированным подходом

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

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

Хотя подавляющее большинство прототип-ориентированных систем основаны на интерпретируемых языках с динамической типизацией, технически возможно добавить прототипирование и в языки со статической проверкой типов. Язык Omega является одним из примеров такой системы.

Конструирование объектов

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

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

//Пример наследования в прототипном программировании 
//на примере языка JavaScript

//Создание нового объекта
var foo = {name: "foo", one: 1, two: 2};

//Создание еще одного нового объекта
var bar = {two: "two", three: 3};

bar.__proto__ = foo; // foo теперь является прототипом для bar

//Если теперь мы попробуем получить доступ к полям foo из bar
//то все получится
bar.one // Равно 1

//Свои поля тоже доступны
bar.three // Равно 3

//Собственные поля выше по приоритету полей прототипов
bar.two; // Равняется "two"

Делегирование

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

Каскадирование

При «чистом» прототипировании — именуемом также каскадным и представленном в Kevo — клонированные объекты не хранят ссылок на свои прототипы. Прототип копируется один-в-один, со всеми методами и атрибутами, и копии присваивается новое имя (ссылка). Это напоминает митоз биологических клеток.

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

В число недостатков можно включить трудности с распространением изменений в системе: модификация прототипа не влечёт за собой немедленное и автоматическое изменение всех его потомков. Тем не менее, Kevo предоставляет дополнительные средства для публикации изменений среди множества объектов, причём на основании их подобия («семейного сходства»), а не по наличию общего предка, что типично для моделей с делегированием.

Другой недостаток в том, что простейшие реализации этой модели приводят к увеличенному (по сравнению с моделью делегирования) расходу памяти, так как каждый клон, пока он не изменён, будет содержать копию данных своего прототипа. Однако эта проблема разрешима оптимальным разделением неизменённых данных и применением «ленивого копирования» — что и было использовано в Kevo.

Критика

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

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

В части эффективности, объявление классов значительно упрощает компилятору задачу оптимизации, делая более эффективными как методы, так и поиск атрибутов в экземплярах. В случае языка Self немалая часть времени была потрачена на разработку таких техник компиляции и интерпретации, которые позволили бы приблизить производительность прототип-ориентированных систем к их класс-ориентированным конкурентам. Дальнейшая работа в этом направлении, а также прогресс в теории JIT-компиляторов привели к тому, что в настоящее время различие между класс- и прототип-ориентированными подходами мало влияет на эффективность результирующего кода. В частности, прототип-ориентированный Lua является одним из самых быстрых интерпретируемых языков и напрямую соперничает со многими компилируемыми,[1] а транслятор языка Lisaac генерирует код ANSI C, практически не уступающий нативному.[2]

Наконец, возможно наиболее общим местом критики против прототипного программирования является то, что сообщество разработчиков программного обеспечения недостаточно хорошо знакомо с ним, несмотря на популярность и распространённость JavaScript. Вдобавок, так как прототип-ориентированные системы сравнительно новы и всё ещё немногочисленны и редки, приёмы разработки с их использованием до сих пор не получили большого распространения.

Языки

Напишите отзыв о статье "Прототипное программирование"

Примечания

  1. [shootout.alioth.debian.org/u32/which-programming-languages-are-fastest.php Which programming languages are fastest?] Computer Language Benchmarks Game.
  2. [shootout.alioth.debian.org/gp4/lisaac.php Lisaac vs. GNU C++]

Литература

  • Иан Грэхем. Объектно-ориентированные методы. Принципы и практика = Object-Oriented Methods: Principles & Practice. — 3-е изд. — М.: «Вильямс», 2004. — С. 880. — ISBN 0-201-61913-X.

Ссылки

  • Пименова Михаила. [b.onchallenge.ru/2009/05/prototype.html Программирование на основе прототипов (prototype): понятие, смысл.] (рус.). Проверено 27 октября 2010. [www.webcitation.org/67lNOmS7t Архивировано из первоисточника 19 мая 2012].
  • [www.intuit.ru/department/internet/flashmx/ Главы 5, 6 и 7 / Flash MX для профессиональных программистов] (рус.). Проверено 27 октября 2010. [www.webcitation.org/67lNQYKqt Архивировано из первоисточника 19 мая 2012].

Отрывок, характеризующий Прототипное программирование

Голова колонны спустилась уже в лощину. Столкновение должно было произойти на этой стороне спуска…
Остатки нашего полка, бывшего в деле, поспешно строясь, отходили вправо; из за них, разгоняя отставших, подходили стройно два баталиона 6 го егерского. Они еще не поровнялись с Багратионом, а уже слышен был тяжелый, грузный шаг, отбиваемый в ногу всею массой людей. С левого фланга шел ближе всех к Багратиону ротный командир, круглолицый, статный мужчина с глупым, счастливым выражением лица, тот самый, который выбежал из балагана. Он, видимо, ни о чем не думал в эту минуту, кроме того, что он молодцом пройдет мимо начальства.
С фрунтовым самодовольством он шел легко на мускулистых ногах, точно он плыл, без малейшего усилия вытягиваясь и отличаясь этою легкостью от тяжелого шага солдат, шедших по его шагу. Он нес у ноги вынутую тоненькую, узенькую шпагу (гнутую шпажку, не похожую на оружие) и, оглядываясь то на начальство, то назад, не теряя шагу, гибко поворачивался всем своим сильным станом. Казалось, все силы души его были направлены на то,чтобы наилучшим образом пройти мимо начальства, и, чувствуя, что он исполняет это дело хорошо, он был счастлив. «Левой… левой… левой…», казалось, внутренно приговаривал он через каждый шаг, и по этому такту с разно образно строгими лицами двигалась стена солдатских фигур, отягченных ранцами и ружьями, как будто каждый из этих сотен солдат мысленно через шаг приговаривал: «левой… левой… левой…». Толстый майор, пыхтя и разрознивая шаг, обходил куст по дороге; отставший солдат, запыхавшись, с испуганным лицом за свою неисправность, рысью догонял роту; ядро, нажимая воздух, пролетело над головой князя Багратиона и свиты и в такт: «левой – левой!» ударилось в колонну. «Сомкнись!» послышался щеголяющий голос ротного командира. Солдаты дугой обходили что то в том месте, куда упало ядро; старый кавалер, фланговый унтер офицер, отстав около убитых, догнал свой ряд, подпрыгнув, переменил ногу, попал в шаг и сердито оглянулся. «Левой… левой… левой…», казалось, слышалось из за угрожающего молчания и однообразного звука единовременно ударяющих о землю ног.
– Молодцами, ребята! – сказал князь Багратион.
«Ради… ого го го го го!…» раздалось по рядам. Угрюмый солдат, шедший слева, крича, оглянулся глазами на Багратиона с таким выражением, как будто говорил: «сами знаем»; другой, не оглядываясь и как будто боясь развлечься, разинув рот, кричал и проходил.
Велено было остановиться и снять ранцы.
Багратион объехал прошедшие мимо его ряды и слез с лошади. Он отдал казаку поводья, снял и отдал бурку, расправил ноги и поправил на голове картуз. Голова французской колонны, с офицерами впереди, показалась из под горы.
«С Богом!» проговорил Багратион твердым, слышным голосом, на мгновение обернулся к фронту и, слегка размахивая руками, неловким шагом кавалериста, как бы трудясь, пошел вперед по неровному полю. Князь Андрей чувствовал, что какая то непреодолимая сила влечет его вперед, и испытывал большое счастие. [Тут произошла та атака, про которую Тьер говорит: «Les russes se conduisirent vaillamment, et chose rare a la guerre, on vit deux masses d'infanterie Mariecher resolument l'une contre l'autre sans qu'aucune des deux ceda avant d'etre abordee»; а Наполеон на острове Св. Елены сказал: «Quelques bataillons russes montrerent de l'intrepidite„. [Русские вели себя доблестно, и вещь – редкая на войне, две массы пехоты шли решительно одна против другой, и ни одна из двух не уступила до самого столкновения“. Слова Наполеона: [Несколько русских батальонов проявили бесстрашие.]
Уже близко становились французы; уже князь Андрей, шедший рядом с Багратионом, ясно различал перевязи, красные эполеты, даже лица французов. (Он ясно видел одного старого французского офицера, который вывернутыми ногами в штиблетах с трудом шел в гору.) Князь Багратион не давал нового приказания и всё так же молча шел перед рядами. Вдруг между французами треснул один выстрел, другой, третий… и по всем расстроившимся неприятельским рядам разнесся дым и затрещала пальба. Несколько человек наших упало, в том числе и круглолицый офицер, шедший так весело и старательно. Но в то же мгновение как раздался первый выстрел, Багратион оглянулся и закричал: «Ура!»
«Ура а а а!» протяжным криком разнеслось по нашей линии и, обгоняя князя Багратиона и друг друга, нестройною, но веселою и оживленною толпой побежали наши под гору за расстроенными французами.


Атака 6 го егерского обеспечила отступление правого фланга. В центре действие забытой батареи Тушина, успевшего зажечь Шенграбен, останавливало движение французов. Французы тушили пожар, разносимый ветром, и давали время отступать. Отступление центра через овраг совершалось поспешно и шумно; однако войска, отступая, не путались командами. Но левый фланг, который единовременно был атакован и обходим превосходными силами французов под начальством Ланна и который состоял из Азовского и Подольского пехотных и Павлоградского гусарского полков, был расстроен. Багратион послал Жеркова к генералу левого фланга с приказанием немедленно отступать.
Жерков бойко, не отнимая руки от фуражки, тронул лошадь и поскакал. Но едва только он отъехал от Багратиона, как силы изменили ему. На него нашел непреодолимый страх, и он не мог ехать туда, где было опасно.
Подъехав к войскам левого фланга, он поехал не вперед, где была стрельба, а стал отыскивать генерала и начальников там, где их не могло быть, и потому не передал приказания.
Командование левым флангом принадлежало по старшинству полковому командиру того самого полка, который представлялся под Браунау Кутузову и в котором служил солдатом Долохов. Командование же крайнего левого фланга было предназначено командиру Павлоградского полка, где служил Ростов, вследствие чего произошло недоразумение. Оба начальника были сильно раздражены друг против друга, и в то самое время как на правом фланге давно уже шло дело и французы уже начали наступление, оба начальника были заняты переговорами, которые имели целью оскорбить друг друга. Полки же, как кавалерийский, так и пехотный, были весьма мало приготовлены к предстоящему делу. Люди полков, от солдата до генерала, не ждали сражения и спокойно занимались мирными делами: кормлением лошадей в коннице, собиранием дров – в пехоте.
– Есть он, однако, старше моего в чином, – говорил немец, гусарский полковник, краснея и обращаясь к подъехавшему адъютанту, – то оставляяй его делать, как он хочет. Я своих гусар не могу жертвовать. Трубач! Играй отступление!
Но дело становилось к спеху. Канонада и стрельба, сливаясь, гремели справа и в центре, и французские капоты стрелков Ланна проходили уже плотину мельницы и выстраивались на этой стороне в двух ружейных выстрелах. Пехотный полковник вздрагивающею походкой подошел к лошади и, взлезши на нее и сделавшись очень прямым и высоким, поехал к павлоградскому командиру. Полковые командиры съехались с учтивыми поклонами и со скрываемою злобой в сердце.
– Опять таки, полковник, – говорил генерал, – не могу я, однако, оставить половину людей в лесу. Я вас прошу , я вас прошу , – повторил он, – занять позицию и приготовиться к атаке.
– А вас прошу не мешивайтся не свое дело, – отвечал, горячась, полковник. – Коли бы вы был кавалерист…
– Я не кавалерист, полковник, но я русский генерал, и ежели вам это неизвестно…
– Очень известно, ваше превосходительство, – вдруг вскрикнул, трогая лошадь, полковник, и делаясь красно багровым. – Не угодно ли пожаловать в цепи, и вы будете посмотрейть, что этот позиция никуда негодный. Я не хочу истребить своя полка для ваше удовольствие.
– Вы забываетесь, полковник. Я не удовольствие свое соблюдаю и говорить этого не позволю.
Генерал, принимая приглашение полковника на турнир храбрости, выпрямив грудь и нахмурившись, поехал с ним вместе по направлению к цепи, как будто всё их разногласие должно было решиться там, в цепи, под пулями. Они приехали в цепь, несколько пуль пролетело над ними, и они молча остановились. Смотреть в цепи нечего было, так как и с того места, на котором они прежде стояли, ясно было, что по кустам и оврагам кавалерии действовать невозможно, и что французы обходят левое крыло. Генерал и полковник строго и значительно смотрели, как два петуха, готовящиеся к бою, друг на друга, напрасно выжидая признаков трусости. Оба выдержали экзамен. Так как говорить было нечего, и ни тому, ни другому не хотелось подать повод другому сказать, что он первый выехал из под пуль, они долго простояли бы там, взаимно испытывая храбрость, ежели бы в это время в лесу, почти сзади их, не послышались трескотня ружей и глухой сливающийся крик. Французы напали на солдат, находившихся в лесу с дровами. Гусарам уже нельзя было отступать вместе с пехотой. Они были отрезаны от пути отступления налево французскою цепью. Теперь, как ни неудобна была местность, необходимо было атаковать, чтобы проложить себе дорогу.