Skip Navigation Linkssmalltalk

​​

Smalltalk


   Этот язык, наверняка,  знаком не всем. Но мы его изучаем в курсе "Объектно- ориентированное программирование" (ООП). Так что же это за язык программирования? Его можно назвать "Родителем" методологии ООП.
​​​​
  Вот что о нем рассказано в статье газеты Компьтер пресс, подготовленной авторами Денисом "Denver" Мигачевым, Владимиром "Vovin" Лешкевичем:  http://www.smalltalk.ru

            Все началось в 1971 году, когда в исследовательскую лабораторию Xerox Palo Alto (Xerox PARC) пришел Alan Kay. Именно этот человек впервые употребил термин object-oriented.
smalltalk.bmpВ лаборатории он возглавил проект по разработке пользовательского интерфейса, основанного на графических пиктограммах, а не на командной строке.
Параллельно с этим он работал над созданием языка программирования, целиком базирующегося на принципах объектно-ориентированного программирования. Он провел аналогию с живым организмом, состоящим из клеток, которые обмениваются между собой информацией только посредством посылки сообщений. 
         Алан Кей

      Его целью было создание системы с рекурсивным дизайном, в которой даже самая малая ее часть повторяет возможности системы в целом. Это должна была быть система, которая развивается посредством последовательного изменения своего состояния. Это коренным образом отличалось от традиционного подхода при конструировании программных систем. Традиционная система представляет множество данных различных типов и имеет различные способы работы с ними: числа целые и вещественные, строки, массивы, множества, функции, объекты, процессы, внешние носители и т.д. Такое разнообразие вносит излишнюю сложность, затрудняет изучение и препятствует хорошей масштабируемости.
 
    В языке Smalltalk основной конструкцией является конструкция посылки сообщения. Язык является динамически типизированным. Это означает, что в объявлениях не содержится указание типов. Все данные являются частными, а все методы — публичными. Простейшие типы данных: число, строка, множество, — являются полноправными объектами, для которых можно определять методы точно так же, как и для любых других объектов.

​      Но Smalltalk — это не просто язык, это динамическая среда исполнения, в которой объекты постоянно создаются, развиваются и уничтожаются. Среда разработки Smalltalk является лучшей иллюстрацией возможностей системы: она целиком написана на самом языке, и любая ее часть может быть динамически модифицирована средствами этой же среды.

     Справедливости ради стоит отметить, что Smalltalk не был создан на пустом месте. Идея динамической среды исполнения с возможностью собственной модификации и средствами мета-программирования была взята из Lisp. Концепция классов пришла из Simula-67, который был первым языком, реализующим некоторые важные принципы объектно-ориентированного программирования.

   А теперь перейдем к перечислению того, что, собственно, Smalltalk дал миру программирования.
 
Объектно-ориентированное программирование

     Еще задолго до появления Smalltalk Алан Кей сформулировал три фундаментальных принципа объектно-ориентированного программирования:
• Объект — базовая единица объектно-ориентированной системы.
• Объекты могут обладать состоянием.
• ​Посылка сообщения — единственный способ обмена информацией между объектами.

   Таким образом, видно, что изначальное определение существенно отличается от привычного нам инкапсуляция — полиморфизм — наследование, которое уже имело место до появления Smalltalk в языке Simula-67.

   Но, к сожалению, исторически сложилось так, что именно Simula послужила образцом для появления многих известных объектно-ориентированных языков. Попробуем рассмотреть, в каком отношении находятся два этих определения.
• Инкапсуляция. Естественным образом следует из первоначального определения, так как объекты заключают в себе свои данные и могут взаимодействовать только посредством посылки сообщения без возможности прямого доступа к внутренней структуре.
Полиморфизм. Входит в понятие посылки сообщения. Любое сообщение может быть послано произвольному объекту, который сам решает, обрабатывать ли его, и если обрабатывать, то каким образом.
Наследование. Это понятие никоим образом не вводится в определении Алана Кея, так как, по сути, это всего лишь удобный механизм для повторного использования кода, что является, скорее, деталью реализации, а не базовым принципом. Если требовать наличия наследования, тогда под определение объектно-ориентированного языка не будут подпадать языки, основанные на прототипах (prototype-based languages), в которых повторное использование реализовано посредством операции делегирования.
 
   Таким образом, видно, что первоначальное определение, данное Аланом Кеем, является более общим. Кроме того, как отмечает сам автор, операция посылки сообщения является чем-то большим, чем операция вызова метода в традиционных языках. Это, пожалуй, самая мощная концепция объектно-ориентированного программирования, отказ от которой сильно снижает эффективность всей идеи.

     Чем же таким особым обладает операция посылки сообщения (message passing) по сравнению с обычным вызовом метода (method invocation), который применяется в статически-типизированных языках?​

    Для начала стоит разобрать, из каких этапов состоят эти две операции. И то, и другое имеет два основных этапа: поиск метода (method lookup) и собственно вызов метода (method invocation).
 
    В статической системе первый этап выполняется компилятором при трансляции исходного кода в машинное представление. Тут снова появляется две альтернативы: раннее связывание (early binding) и позднее связывание (late binding). В первом случае компилятор заранее знает метод, который получит управление после операции вызова. Во втором же для каждого класса (интерфейса) компилятор строит свою таблицу методов и использует индекс для извлечения результирующего метода на этапе выполнения. Первый механизм также называется статической диспетчеризацией (static dispatch), второй — статической диспетчеризацией на основе таблицы виртуальных методов (static vtable-based dispatch). Операция посылки сообщения в динамической системе осуществляет оба этапа на стадии выполнения программы. Поиск метода (method lookup) выполняется каждый раз перед вызовом метода (method invocation). При этом, если результирующий метод не найден, выполняется поиск метода doesNotUnderstand:, который является стандартным обработчиком события "метод не найден". В среде разработки это вызовет окно отладчика, в работающей системе можно либо прервать текущий процесс/нить или продолжить выполнение с занесением сообщения в лог-файл. Описанный механизм называется динамической диспетчеризацией (dynamic dispatch).
 
​   Таким образом, операция посылки сообщения не гарантирует, что она будет обработана каким-то определенным образом или вообще будет обработана. Такое ослабление дает дополнительный уровень абстракции и возможности для повторного использования кода.

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

   Области, в которых это находит применение: персистентность, распределенные системы, профилирование, сбор статистической информации и т.д.

     К тому же, сама семантика посылки сообщения может быть модифицирована для привнесения новых возможностей в систему: аспектно-ориентированное программирование, контрактное проектирование, предусловия и постусловия и т.д. Именно операция посылки сообщения является тем, что обеспечивает описанный Аланом Кеем рекурсивный дизайн системы, при котором даже наименьшая ее часть может обладать не меньшими возможностями, чем система в целом.

<< Назад