Я (язык программирования)


Из Википедии, свободной энциклопедии
  (Перенаправлено с Self (компьютерный язык) )
Перейти к навигации Перейти к поиску

Self — это объектно-ориентированный язык программирования, основанный на концепции прототипов . Self начинался как диалект Smalltalk , динамически типизированный и использующий JIT -компиляцию , а также подход к объектам, основанный на прототипах: он впервые использовался в качестве экспериментальной тестовой системы для языкового дизайна в 1980-х и 1990-х годах. . В 2006 году Self все еще разрабатывался в рамках проекта Klein, который представлял собой виртуальную машину Self, полностью написанную на Self. Последняя версия — 2017.1, выпущенная в мае 2017 г. [2]

Несколько методов компиляции «точно в срок» были впервые применены и улучшены в исследованиях Self, поскольку они требовались, чтобы позволить объектно-ориентированному языку очень высокого уровня работать на вдвое меньшей скорости, чем оптимизированный C. Большая часть разработки Self происходила в Sun. Микросистемы и методы, которые они разработали, позже были развернуты для виртуальной машины Java HotSpot .

В какой-то момент версия Smalltalk была реализована в Self. Поскольку он мог использовать JIT, это также дало очень хорошую производительность. [3]

История

Self был разработан в основном Дэвидом Ангаром и Рэндаллом Смитом в 1986 году, когда они работали в Xerox PARC . Их цель состояла в том, чтобы продвигать современное состояние исследований в области объектно-ориентированных языков программирования после того, как лаборатории выпустили Smalltalk-80 и начали серьезно воспринимать его в отрасли. Они переехали в Стэнфордский университет и продолжили работу над языком, создав первый работающий компилятор Self в 1987 году. В этот момент внимание переключилось на попытку создать для Self целую систему, а не только язык.

Первый публичный релиз состоялся в 1990 году, а в следующем году команда перешла в Sun Microsystems , где продолжила работу над языком. За этим последовало несколько новых выпусков, пока в 1995 году версия 4.0 не стала в значительной степени бездействующей. Версия 4.3 была выпущена в 2006 году и работала на Mac OS X и Solaris . Новый выпуск в 2010 году, [4] версия 4.4, был разработан группой, состоящей из некоторых из оригинальной команды и независимых программистов, и доступен для Mac OS X и Linux , как и все последующие версии. Последующая версия 4.5 была выпущена в январе 2014 года [5] , а три года спустя в мае 2017 года была выпущена версия 2017.1.

Self также вдохновил на создание ряда языков, основанных на его концепциях. Наиболее примечательными, пожалуй, были NewtonScript для Apple Newton и JavaScript , используемый во всех современных браузерах. Другие примеры включают Ио , Лизаак и Агору . Распределенная объектная система IBM Tivoli Framework , разработанная в 1990 году, на самом низком уровне была объектной системой на основе прототипа, вдохновленной Self.

Языки программирования на основе прототипов

Традиционные объектно-ориентированные языки, основанные на классах, основаны на глубоко укоренившейся двойственности:

  1. Классы определяют основные качества и поведение объектов.
  2. Экземпляры объектов являются частными проявлениями класса.

Например, предположим, что у объектов Vehicleкласса есть имя и возможность выполнять различные действия, например ездить на работу и доставлять строительные материалы . Bob's car— это конкретный объект (экземпляр) класса Vehicleс именем «машина Боба». Теоретически можно отправить сообщение Bob's car, чтобы доставить строительные материалы .

Этот пример показывает одну из проблем, связанных с этим подходом: автомобиль Боба, который оказался спортивным автомобилем, не может перевозить и доставлять строительные материалы (в каком-либо осмысленном смысле), но это возможность, которую Vehicleмоделируют. Более полезная модель возникает из-за использования подклассов для создания специализаций Vehicle; например Sports Carи Flatbed Truck. Только объекты этого класса Flatbed Truckдолжны обеспечивать механизм доставки строительных материалов ; спортивным автомобилям, которые плохо приспособлены для такой работы, достаточно ехать быстро . Однако эта более глубокая модель требует большего понимания во время проектирования, понимания, которое может проявиться только по мере возникновения проблем.

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

Динамические языки, такие как Smalltalk, допускали такого рода изменения с помощью хорошо известных методов в классах; изменив класс, объекты, основанные на нем, изменили бы свое поведение. Однако такие изменения нужно было вносить очень осторожно, поскольку другие объекты, основанные на том же классе, могли ожидать такого «неправильного» поведения: «неправильное» часто зависит от контекста. (Это одна из форм проблемы хрупкого базового класса .) Кроме того, в таких языках, как C++ , где подклассы могут быть скомпилированы отдельно от суперклассов, изменение суперкласса может фактически нарушить предварительно скомпилированные методы подкласса. (Это еще одна форма проблемы хрупкого базового класса, а также одна из форм проблемы хрупкого бинарного интерфейса .)

В Self и других языках, основанных на прототипах, двойственность между классами и экземплярами объектов устранена.

Вместо того, чтобы иметь «экземпляр» объекта, основанного на каком-то «классе», в Self делается копия существующего объекта и изменяется. Таким образом Bob's car, будет создано путем создания копии существующего объекта «Автомобиль», а затем добавления метода быстрой езды , моделирующего тот факт, что это Porsche 911 . Базовые объекты, используемые в основном для создания копий, называются прототипами . Утверждается, что этот метод значительно упрощает динамизм. Если существующий объект (или набор объектов) оказывается неадекватной моделью, программист может просто создать модифицированный объект с правильным поведением и использовать его вместо этого. Код, использующий существующие объекты, не изменяется.

Описание

Объекты Self представляют собой набор «слотов». Слоты — это методы доступа, которые возвращают значения, и размещение двоеточия после имени слота устанавливает значение. Например, для слота под названием «имя»,

мое  имя

возвращает значение в имени и

мое  имя: 'фу'

устанавливает его.

Self, как и Smalltalk, использует блоки для управления потоком данных и других задач. Методы — это объекты, содержащие код в дополнение к слотам (которые они используют для аргументов и временных значений), и могут быть помещены в слот Self, как и любой другой объект: например, число. Синтаксис остается одинаковым в любом случае.

Обратите внимание, что в Self нет различия между полями и методами: все является слотом. Поскольку доступ к слотам через сообщения составляет большую часть синтаксиса в Self, многие сообщения отправляются на «себя», а «себя» можно не указывать (отсюда и название).

Основной синтаксис

Синтаксис доступа к слотам похож на синтаксис Smalltalk. Доступны три вида сообщений:

унарный
receiver slot_name
бинарный
receiver + argument
ключевое слово
receiver keyword: arg1 With: arg2

Все сообщения возвращают результаты, поэтому получатель (если присутствует) и аргументы сами могут быть результатом других сообщений. После сообщения точка означает, что Self отбросит возвращаемое значение. Например:

'Привет мир!'  печать .

Это самостоятельная версия программы hello world . Синтаксис 'указывает на литеральный строковый объект. Другие литералы включают числа, блоки и общие объекты.

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

допустимо:  основание  низ  между:  лигатурой  низ  +  высота  И:  основание  верх  /  масштабный  коэффициент .

может быть проанализирован однозначно и означает то же, что и:

допустимо: (( основание  внизу ) между: (( лигатура  внизу ) +  высота ) И: (( основание  вверху ) / ( коэффициент масштабирования ))) .

В Smalltalk-80 это же выражение выглядело бы так:

действительно  :=  собственное  основание  внизу  между:  собственной  лигатурой  внизу  +  собственной  высотой  и:  собственным  основанием  вверху  /  коэффициентом собственного  масштаба  .

предполагая base, что ligature, heightи scaleне были переменными экземпляра , selfа фактически были методами.

Создание новых объектов

Рассмотрим немного более сложный пример:

labelWidget  copy  label:  "Hello, World!" .

делает копию объекта «labelWidget» с сообщением копирования (на этот раз без ярлыка), затем отправляет ему сообщение, чтобы поместить «Hello, World» в слот с именем «label». Теперь что-то с этим делать:

( настольное  активное окно ) draw: ( labelWidget  copy  label:  'Hello, World!' ) .

В этом случае (desktop activeWindow)выполняется сначала, возвращая активное окно из списка окон, о которых известно объекту рабочего стола. Далее (читай изнутри наружу, слева направо) код, который мы рассмотрели ранее, возвращает labelWidget. Наконец, виджет отправляется в слот рисования активного окна.

Делегация

Теоретически каждый объект «Я» представляет собой автономную сущность. Self не имеет ни классов, ни метаклассов. Изменения в одном объекте не влияют ни на какой другой, но в некоторых случаях желательно, чтобы они это сделали. Обычно объект может понимать только сообщения, соответствующие его локальным слотам, но, имея один или несколько слотов, указывающих на родительские объекты, объект может делегировать любое сообщение, которое он сам не понимает, родительскому объекту. Любой слот можно сделать родительским указателем, добавив звездочку в качестве суффикса. Таким образом, Self обрабатывает обязанности, которые используют наследование в языках, основанных на классах. Делегирование также можно использовать для реализации таких функций, как пространства имен и лексическая область видимости .

Например, предположим, что определен объект под названием «банковский счет», который используется в простом бухгалтерском приложении. Обычно этот объект создается с методами внутри, например, «депозит» и «снятие», и любыми слотами данных, которые им необходимы. Это прототип, который отличается только тем, как он используется, поскольку он также является полнофункциональным банковским счетом.

Черты

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

В этом примере объект «банковский счет» не будет иметь методов депозита и снятия, но будет иметь в качестве родителя объект, у которого есть. Таким образом, можно создать много копий объекта банковского счета, но мы все же можем изменить их поведение, изменив слоты в этом корневом объекте.

Чем это отличается от традиционного класса? Хорошо подумайте о значении:

родитель myObject  :  someOtherObject .

Этот отрывок изменяет «класс» myObject во время выполнения, изменяя значение, связанное со слотом «родительский *» (звездочка является частью имени слота, но не соответствующих сообщений). В отличие от наследования или лексической области видимости, объект делегата можно изменить во время выполнения.

Добавление слотов

Объекты в Self могут быть изменены для добавления дополнительных слотов. Это можно сделать с помощью графической среды программирования или с помощью примитива '_AddSlots:'. Примитив имеет тот же синтаксис, что и обычное сообщение с ключевым словом, но его имя начинается с символа подчеркивания. Следует избегать примитива _AddSlots, потому что он остался от ранних реализаций. Однако мы покажем это в примере ниже, потому что это делает код короче.

В более раннем примере речь шла о рефакторинге простого класса Vehicle, чтобы можно было различать поведение легковых и грузовых автомобилей. В «Я» это можно было бы сделать примерно так:

_ AddSlots: ( |  транспортное средство  <- ( | родитель *  =  черты, которые можно  клонировать| ) | ) .

Поскольку получатель примитива '_AddSlots:' не указан, это "я". В случае выражений, введенных в приглашении, это объект, называемый «лобби». Аргументом для '_AddSlots:' является объект, слоты которого будут скопированы в приемник. В данном случае это буквальный объект ровно с одним слотом. Имя слота — «транспортное средство», а его значение — еще один буквальный объект. Обозначение «<-» подразумевает второй слот под названием «транспортное средство:», который можно использовать для изменения значения первого слота.

«=» указывает на постоянный слот, поэтому соответствующий «родительский:» отсутствует. Литеральный объект, который является начальным значением «транспортное средство», включает один слот, поэтому он может понимать сообщения, связанные с клонированием. Действительно пустой объект, обозначенный как (| |) или проще как (), вообще не может получать никаких сообщений.

транспортное средство  _ AddSlots: ( |  имя  <-  'автомобиль' | ) .

Здесь получатель — это предыдущий объект, который теперь будет включать в себя слоты «имя» и «имя:» в дополнение к «родителю*».

_ AddSlots: ( |  sportsCar  <-  копия автомобиля  | ) . sportsCar _ AddSlots: ( | driveToWork = ( '' какой - то код, это метод ' ' ) | ) .         

Хотя раньше «транспортное средство» и «спортивный автомобиль» были совершенно одинаковыми, теперь последний включает новый слот с методом, которого нет в оригинале. Методы могут быть включены только в константные слоты.

_ AddSlots: ( |  porsche911  <-  копия спортивного автомобиля  | ) . porsche911 имя: «Бобс Порше» .  

Новый объект «porsche911» начинался точно так же, как «sportsCar», но последнее сообщение изменило значение его слота «name». Обратите внимание, что оба по-прежнему имеют одинаковые слоты, даже если один из них имеет другое значение.

Окружающая обстановка

Одной из особенностей Self является то, что он основан на той же системе виртуальных машин , что и более ранние системы Smalltalk. То есть программы не являются автономными сущностями, как в таких языках, как C , но для запуска им требуется вся их среда памяти. Это требует, чтобы приложения поставлялись в виде фрагментов сохраненной памяти, известных как моментальные снимки или образы .. Одним из недостатков этого подхода является то, что изображения иногда бывают большими и громоздкими; однако отладка образа часто проще, чем отладка традиционных программ, потому что состояние выполнения легче проверить и изменить. (Разница между разработкой на основе исходного кода и разработкой на основе изображений аналогична разнице между программированием на основе классов и прототипным объектно-ориентированным программированием.)

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

Представление

Самостоятельные виртуальные машины достигли производительности примерно в половину скорости оптимизированного C в некоторых тестах. [6]

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

Вывоз мусора

Сборщик мусора для Self использует сборку мусора по поколениям , которая разделяет объекты по возрасту. Используя систему управления памятью для записи страниц, можно поддерживать барьер записи. Этот метод дает отличную производительность, хотя после некоторого времени работы может произойти полная сборка мусора, что займет значительное время. [ расплывчато ]

Оптимизации

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

Смотрите также

  • Сесил (язык программирования)

использованная литература

  1. ^ Унгар, Дэвид; Смит, Рэндалл Б. (2007). "Себя". Материалы Третьей конференции ACM SIGPLAN по истории языков программирования (HOPL III) . дои : 10.1145/1238844.1238853 . ISBN 9781595937667. S2CID  220937663 .
  2. ^ "Я "Мандарин" 2017.1" . 24 мая 2017 года. Архивировано из оригинала 24 мая 2017 года . Проверено 24 мая 2017 г.
  3. ^ Волко, Марио (1996). «Я включает: Smalltalk». Семинар по языкам на основе прототипов, ECOOP '96, Линц, Австрия .
  4. Викискладе есть медиафайлы по теме Self 4.4 . 16 июля 2010 г. Архивировано из оригинала 5 декабря 2017 г .. Проверено 24 мая 2017 г.
  5. ^ «Выпущена самостоятельная кряква (4.5.0)» . 12 января 2014 года. Архивировано из оригинала 6 декабря 2017 года . Проверено 24 мая 2017 г.
  6. ^ Агесен, Оле (март 1997 г.). «Проектирование и реализация Pep, JIT-переводчика Java» . солнце.com . Архивировано из оригинала 24 ноября 2006 года.
  7. ^ [1] [ мертвая ссылка ]

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

  • Опубликованные статьи о себе
  • Чемберс, К. (1992), Дизайн и реализация компилятора SELF, оптимизирующего компилятора для объектно-ориентированных языков программирования , Стэнфордский университет , CiteSeerX  10.1.1.30.1652
  • Цикл из четырех статей "Среда и язык программирования Self"

внешняя ссылка

  • Официальный сайт
  • себя на GitHub
  • Бывшая самостоятельная домашняя страница в Sun Microsystems
  • Альтернативный источник документов о Self от UCSB (зеркало страницы документов Sun)
  • Проект Мерлин
  • Самостоятельно портирован на Linux (без особых оптимизаций)
  • Приложение для автоматизированного рефакторинга на sourceforge.net, написанное для себя и в нем.
  • Страница Гордона о себе
  • Система объектов Prometheus на вики Community Scheme
  • Видео, демонстрирующее себя
  • dSelf: распределенное расширение для делегирования и языка Self
Получено с https://en.wikipedia.org/w/index.php?title=Self_(programming_language)&oldid=1062063863 "