- •1.Введение
- •1.1.Декомпозиция и абстракция
- •1.2.Абстракция
- •1.2.1.Абстракция через параметризацию
- •1.2.2.Абстракция через спецификацию
- •1.2.3.Виды абстракций
- •3.Процедурная абстракция
- •3.2.Спецификации
- •3.3.Спецификации процедурных абстракций
- •3.4.Реализация процедур
- •3.5.Более обобщенные процедуры
- •3.6.Создание процедурных абстракций
- •3.7.Заключение
- •4.Абстракции данных
- •4.1.Спецификации для абстракций данных
- •4.2.1.Реализация на языке clu
- •4.2.2.Замечания по поводу операций up и down
- •4.3.Использование абстракций данных
- •4.4.Реализация полиномов
- •4.5.Пояснения для понимания реализаций
- •4.5.1.Функция абстракции
- •4.5.2.Инвариант представления
- •4.6.3.Сохранение инварианта представления
- •4.5.4.Изменяемые представления
- •4.6.Параметризованные абстракции данных
- •4.7.Списки
- •4.8.Упорядоченные списки
1.2.Абстракция
Процесс абстракции может быть рассмотрен как некоторое обобщение. Он позволяет нам забыть об информации и, следовательно, рассматривать различные предметы так, как если бы они были эквивалентны. Мы выполняем это в надежде упростить наш анализ, отделяя существенные атрибуты от несущественных. Однако при этом важно знать, что критерий такого отделения во многом зависит от контекста. В контексте школьного курса мы учимся абстрагировать от (8/3)*3 и 5+3к понятию, представленному числом 8.В дальнейшем мы узнаем, что при работе на большинстве вычислительных машин такая абстракция приводит к неприятностям.
Например, рассмотрим структуру, приведенную на рис. 1.1. Понятием здесь является «млекопитающие». Все млекопитающие обладают определенными общими характеристиками. Например, все женские особи этого класса вырабатывают молоко. На таком уровне абстракции мы фокусируемся именно на этих общих характеристиках и игнорируем различия между существующими видами млекопитающих.
На нижнем уровне абстракции мы сосредоточиваем свое внимание на конкретных представителях семейства млекопитающих. В этом случае мы можем абстрагироваться, рассматривая не отдельных представителей или даже особей, а группы родственных особей, например, приматов или грызунов. Здесь опять мы рассматриваем общие характеристики, например тот факт, что все приматы носят своих детенышей, а не отличия между, скажем, человеком и шимпанзе. Эти отличия остаются существенными и на более низких уровнях абстракции.
Млекопитающие
... Приматы Грызут ...
Обезьяна Человек
Рис. 1.1.Иерархия абстракций.
Иерархия абстракций, показанная на рис. 1.1,относится к вполне определенной области зоологии, однако она приложима также и к другим областям этой науки. Более машинно-ориентированным примером, весьма полезным при составлении большей части программ, является концепция «файла». Файлы абстрагированы от конкретного носителя, реализуя долговременное и постоянно доступное хранилище поименованных единиц. Операционные системы отличаются по способам работы с файлами. Например, структура имен файлов может меняться от системы к системе. Изменяется также и способ их размещения на устройствах внешней памяти.
В данной книге мы рассмотрим различные виды абстракций и общие принципы применения их в программах. Наиболее существенным достижением в этой области является на сегодняшний день развитие языков высокого уровня. Имея дело непосредственно с конструкциями языка высокого уровня, а не с различными наборами машинных инструкций, в которые данные конструкции могут быть транслированы, программист существенно упрощает свой труд.
В последние годы программистов перестал удовлетворять уровень абстракции, достигаемый в программах, написанных даже на языке высокого уровня. Рассмотрим, например, фрагмент программы на рис. 1.2.
found := false i :== lowbound (a) while i<highbound (a) + I do if a [i] = e then z := i found := true end i:= i+ I end
Рис. 1.2.Два фрагмента программы.
found := false i := highbound (a) while i>lo-wbound (a) — I do if a [i]=e then z := i found := true end i:= i—1 end
На уровне абстракции, определенном использованным языком высокого уровня, очевидно, что приведенные фрагменты отличаются друг от друга: если е присутствует в а, то первый фрагмент отыскивает индекс его первого вхождения, а второй —индекс последнего вхождения. Первая программа устанавливает iв high-bound(а) + 1,а вторая —в lowbound (1) — 1.Обе программы, однако, были написаны для выполнения одной и той же функции: установить в foundзначение false,если е отсутствует в а, а в противном случае установить в found trueи в z—индекс вхождения е в а. Если нам необходимо выполнение именно этого требования, то становится очевидным, что приведенные фрагменты программ не находятся на требуемом уровне абстракции.
Одним из подходов к решению такой проблемы является создание языков «очень высокого уровня», реализованных на базе некоторого фиксированного набора относительно обобщенных универсальных структур данных и мощном наборе примитивов, используемых для манипуляции с ними. Например, рассмотрим язык, в котором имеются примитивы is_inи index_of,позволяющие осуществлять соответствующие операции над массивами. Тогда рассматриваемая задача легко реализуется следующим образом:
found := is_in (a, e)
if found then z :== index_of (a, e) end
Недостатком такого подхода является предположение о том, что разработчик языка включит в него большинство абстракций, которые могут понадобиться пользователю. Предвидеть все возможные ситуации довольно затруднительно. Однако, даже если это и удалось бы сделать, получившийся язык содержал бы столь много встроенных абстракций, что работа с ним стала бы невозможной.
Альтернативой может быть создание таких языковых механизмов, которые позволяют программисту создавать свои собственные абстракции по мере необходимости. Наиболее распространенным механизмом такого рода является использованиепроцедур.Разделяя в программе тело процедуры и обращения к ней, язык высокого уровня реализует тем самым два важных метода абстракции:абстракция через параметризациюиабстракция через спецификацию.