Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

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

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

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

История [ править ]

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

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

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

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

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

  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 . Базовые объекты, которые используются в основном для создания копий, называются прототипами . Утверждается, что этот метод значительно упрощает динамизм. Если существующий объект (или набор объектов) оказывается неадекватной моделью, программист может просто создать измененный объект с правильным поведением и использовать его вместо этого. Код, использующий существующие объекты, не изменяется.

Описание [ править ]

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

мое  имя

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

myPerson  name: 'foo'

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

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

Обратите внимание, что в Self нет различия между полями и методами: все - это слот. Поскольку доступ к слотам через сообщения составляет большую часть синтаксиса в 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  скопируйте  метку:  'Hello, World!' .

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

( рабочий стол  activeWindow ) draw: ( labelWidget  copy  label:  'Hello, World!' ) .

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

Делегирование [ править ]

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

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

Черты характера [ править ]

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

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

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

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

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

Добавление слотов [ править ]

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

Предыдущий пример касался рефакторинга простого класса под названием Vehicle, чтобы иметь возможность различать поведение между легковыми и грузовыми автомобилями. В Self это можно сделать примерно так:

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

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

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

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

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

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

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

_ AddSlots: ( |  porsche911  <-  sportsCar  copy  | ) . Название porsche911  : «Бобы Порше» .

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

Окружающая среда [ править ]

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

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

Производительность [ править ]

В некоторых тестах производительность собственных виртуальных машин была примерно вдвое меньше, чем у оптимизированного языка C. [5]

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

Сборка мусора [ править ]

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

Оптимизация [ править ]

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

См. Также [ править ]

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

Ссылки [ править ]

  1. ^ "Self" Mandarin "2017.1" . 24 мая 2017. Архивировано из оригинала 24 мая 2017 года . Дата обращения 24 мая 2017 .
  2. ^ Wolczko, Марио (1996). "self включает: Smalltalk". Семинар по языкам на основе прототипов, ECOOP '96, Линц, Австрия .
  3. ^ "Самостоятельная версия 4.4 выпущена" . 16 июля 2010. Архивировано из оригинала 5 декабря 2017 года . Дата обращения 24 мая 2017 .
  4. ^ «Выпущен Self Mallard (4.5.0)» . 12 января 2014. Архивировано из оригинала 6 декабря 2017 года . Дата обращения 24 мая 2017 .
  5. ^ Agesen, Ole (март 1997). «Разработка и реализация Pep, JIT-переводчика Java» . sun.com . Архивировано из оригинального 24 ноября 2006 года.
  6. ^ [1] [ неработающая ссылка ]

Дальнейшее чтение [ править ]

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

Внешние ссылки [ править ]

  • Официальный веб-сайт
  • я на GitHub
  • Бывшая собственная домашняя страница в Sun Microsystems
  • Альтернативный источник статей о себе из UCSB (зеркало для страницы документов Sun)
  • Мерлин Проект
  • Самостоятельно портирован на Linux (без многих оптимизаций)
  • Приложение автоматического рефакторинга на sourceforge.net, написанное для Self и на нем
  • Страница Гордона о себе
  • Система объектов Prometheus на вики-странице схемы сообщества
  • Видео, демонстрирующее себя
  • dSelf: распределенное расширение для делегирования и языка Self