Опубликован: 23.10.2005 | Доступ: свободный | Студентов: 4089 / 201 | Оценка: 4.44 / 4.19 | Длительность: 33:04:00
Специальности: Программист
Лекция 17:

От Simula к Java и далее: основные ОО-языки и окружения

Smalltalk

Идеи языка Smalltalk были заложены в 1970 г. Аланом Кейем в Университете Юты, в то время его выпускником и членом группы, занимающейся графикой. Алана попросили познакомиться с компилятором расширения языка Algol 60, только что доставленного из Норвегии. (Расширением языка Algol был, конечно, язык Simula.) Изучая его, он понял, что компилятор в действительности выходит за пределы Algol и реализует ряд идей, непосредственно относящихся к его работе над графикой. Когда Кей позднее стал сотрудником Xerox Palo Alto Research Center - PARC, он заложил те же принципы в основу своего видения современной среды программирования на персональных компьютерах. В первоначальную разработку Smalltalk в центре Xerox PARC также внесли вклад А. Гольдберг и Д. Инголс (Adele Goldberg, Daniel Ingalls).

Smalltalk-72 развился в Smalltalk-76, затем в Smalltalk-80. Были разработаны версии для ряда машин - вначале для Xerox, а затем как промышленные разработки. Сегодня реализации Smalltalk доступны на большинстве известных платформ.

Языковой стиль

Язык Smalltalk сочетает в себе идеи Simula и свободный, бестиповый стиль языка Lisp. Статическая проверка типов не производится, что противоречит подходу, предлагаемому в данной книге. Основное внимание в языке и окружении уделяется динамическому связыванию. Решение о том, можно ли применить подпрограмму к объекту, происходит во время выполнения.

У Smalltalk своя терминология. Подпрограмма называется "методом", применение подпрограммы к объекту называется "посланием сообщения" объекту (чей класс должен находить соответствующий метод для обработки сообщения).

Другой важной чертой отличия стиля Smalltalk от изучаемого в этой книге является отсутствие ясного различия между классами и объектами. В системе Smalltalk все - объекты, включая и сами классы. Класс рассматривается как объект класса более высокого уровня, называемого метаклассом. Это позволяет иерархии классов включать все элементы системы, в корне иерархии находится класс самого высокого уровня, называемый object. Корень поддерева, содержащий только классы, - это метакласс class. Аргументация для этого подхода такова:

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

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

Сообщения

Smalltalk определяет три основные формы сообщений (и связанных с ними методов): унарные, бинарные и заданные ключевым словом. Унарные сообщения задают вызовы подпрограмм без аргументов:

acc1 balance

Здесь сообщение balance посылается объекту, связанному с acc1. Запись эквивалентна нотации acc1.balance, используемой в Simula и в данной книге. Сообщения могут, как в данном случае, возвращать значения. Сообщения с ключевыми словами вызывают подпрограммы с аргументами:

point1 translateBy: vector1
window1 moveHor: 5 Vert: -3

Заметьте, используется ключевой способ при передаче аргументов. При этом частью установленного стиля Smalltalk является объединение имени вызываемого сообщения и первого аргумента, что порождает такие идентификаторы, как translateBy или moveHor. Соответствующая запись в Simula или нашей нотации была бы point1.translate (vector1) и window1.move (5, -3).

Бинарные сообщения, похожие на инфиксные функции Ada и нотацию этой книги, служат для примирения подхода "все является объектом" с традиционными арифметическими нотациями. Большинство людей, по крайней мере старшего поколения, изучавших арифметику до объектной технологии, скорее напишут 2+3, чем:

2 addMeTo: 3

Бинарные сообщения Smalltalk дают первую форму записи как синоним второй. Однако здесь есть заминка: приоритет операций. Выражение a + b * c здесь означает не то, что вы думаете - (a + b) * c. Для изменения порядка разработчики могут использовать скобки. Унарные сообщения предшествуют по старшинству бинарным, так что window1 height + window2 height имеет ожидаемое значение.

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

x | |
\\
    \uparrow xx
\\
y | |
\\
    \uparrow yy
\\
scale: scaleFactor | |
\\
    xx \leftarrow xx \cdot scaleFactor
\\
    yy \leftarrow yy \cdot scaleFactor

Методы x и y возвращают значения переменных экземпляров (атрибутов) xx и yy. Стрелка вверх означает, что следующее выражение - это величина, возвращаемая методом отправителю соответствующего сообщения. Метод scale имеет аргумент scaleFactor. Вертикальные полосы | | будут ограничивать локальные переменные, если они есть.

Наследование - важная часть подхода Smalltalk, но кроме некоторых экспериментальных реализаций, оно ограничивается единичным наследованием. Чтобы дать возможность при переопределении метода вызывать оригинальную версию, Smalltalk позволяет разработчику ссылаться на объект, рассматриваемый как экземпляр класса родителя, посредством имени super, как в:

aFunction: anArgument |...|
    ... super aFunction: anArgument ...

Интересно сравнить этот подход с техникой, основанной на Precursor, и дублирующим наследованием.

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

Динамический контроль типов делает неуместными некоторые концепции, развитые ранее в этой книге: Smalltalk не нуждается в языковой поддержке универсальности, поскольку структуры, подобные стеку, могут содержать элементы любого типа без какой бы то ни было статической проверки согласованности. Становятся ненужными отложенные подпрограммы, поскольку для вызова x f (эквивалент x.f ) нет статического правила, требующего, чтобы определенный класс обеспечивал метод f. Если класс C получает сообщение, соответствующее методу, чьи эффективные определения появляются только в потомках C, то Smalltalk лишь обеспечит возбуждение ошибки во время выполнения, Например, в классе FIGURE можно реализовать rotate таким образом:

rotate: anAngle around: aPoint | |
    self shouldNotImplement

Метод shouldNotImplement включается в общий класс объект и возвращает сообщение об ошибке. Нотация self означает текущий объект.

Окружение и производительность

Многие из достоинств Smalltalk пришли из поддерживающей среды программирования. Он одним из первых включил инновационную для того времени интерактивную технику. Многое пришло из других проектов Xerox PARC, разрабатываемых одновременно со Smalltalk. Ставшие теперь обычными окна, значки, соединение текста и графики, выпадающие контекстные меню, использование мыши - все это идет из Palo Alto тех лет. Такие современные инструменты ОО-среды, как браузеры, инспекторы и ОО-отладчики восходят корнями к окружению Smalltalk.

Как и в Simula, все коммерческие реализации языка поддерживают сборку мусора. Smalltalk-80 и последующие реализации признаны за их библиотеки базовых классов, охватывающие важные абстракции, такие как "коллекции" и "словари", ряд графических понятий.

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

Smalltalk: оценка

Smalltalk явился инструментом, соединившим интерактивную технику с концепциями объектной технологии, превратив абстрактные объекты Simula в визуальные объекты, вдруг ставшие понятными и привлекательными для публики. Simula повлиял на методологию программирования и произвел впечатление на экспертов языков; Smalltalk со времени знаменитого выпуска Byte в августе 1981 г. поразил массы.

Учитывая, насколько идеи Smalltalk современны сегодня, поражаешься коммерческому успеху языка в начале 90-х гг. Этот феномен отчасти можно объяснить двумя независимыми явлениями, оба из которых имеют природу " от противного ":

  • Эффект "испытай следующего в списке". Многие, привлеченные к объектной технологии элегантностью концепций, были разочарованы смешанными подходами, существующими, например, в C++. В поисках лучшего воплощения концепций они часто обращались к подходу, представляемому в компьютерных публикациях как чистый ОО-подход: Smalltalk. Многие разработчики Smalltalk - те, кто "просто говорят нет" C и похожим на C разработкам.
  • Упадок Lisp. Долгое время многие компании полагались на варианты Lisp (язык Prolog и другие подходы, основанных на искусственном интеллекте) для проектов, включающих быструю разработку прототипов и проведение экспериментов. Начиная с середины 70-х, однако, Lisp исчез со сцены; Smalltalk естественно занял образовавшуюся пустоту.

Последнее замечание дает хорошее представление о месте Smalltalk. Smalltalk - отличный инструмент для прототипирования и экспериментов, особенно с визуальными интерфейсами (в этом он конкурирует с современными инструментами, такими как Delphi от Borland или Visual Basic от Microsoft). Но он во многом остался в стороне от более поздних разработок в методологии инженерии программ. Об этом свидетельствует отсутствие статической типизации, механизмов утверждений, дисциплинированной обработки исключений, отложенных классов - все это имеет значение для систем, решающих критически важные задачи, или просто любой системы, чье правильное поведение во время выполнения важно для разработавшей ее организации. Остаются и проблемы эффективности.

Урок ясен: было бы неразумным, по моему мнению, сегодня использовать Smalltalk для серьезных разработок.