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

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

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

Содержание

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Критика

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

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

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

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

Языки

  • Actor-Based Concurrent Language, ABCL: ABCL/1, ABCL/R, ABCL/R2, ABCL/c+
  • Agora
  • Cecil
  • Cel
  • ECMAScript a.k.a. ActionScript, DMDScript, JavaScript (первоначально Mocha, затем LiveScript), JScript
  • Factor
  • Io
  • Lua
  • MOO
  • NewtonScript
  • Obliq
  • OpenLaszlo
  • REBOL
  • Self
  • Slate
  • TADS

Смотри также

 
Начальная страница  » 
А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ы Э Ю Я
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9 Home