Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
48
Добавлен:
23.03.2015
Размер:
396 Кб
Скачать
☆

4.2.2. Замечания по поводу операций up и down

Полезно представлять себе операцию up как окружение объ' екта типа представления непроницаемой заслонкой. Тому, кто использует операцию up, сквозь эту заслонку не видно представ­ления. Значение объекта можно исследовать только вызовом при­митивных операций, соответствующих типу объекта. Например, пользователь не видит массива, который представляет набор intset, но может сказать, какие элементы имеются в наборе, и может добавлять или удалять элементы, обращаясь к соответ­ствующим операциям.

Операция down производит обратное действие по отношению к up — она убирает заслонку. Если бы для пользователя имелась возможность обращаться к down, то ему было бы доступно кон­кретное представление абстрактного объекта и выгоды абстрак­ции данных были бы утеряны. Поэтому язык CLU позволяет использовать операцию down только в кластере, который реали­зует объект.

Чтобы избежать возникновения фальшивых объектов, огра­ничивается также и использование операции up. Если бы эту операцию можно было использовать вне определяющего кластера, было бы возможно создавать объекты, которые выглядели как объекты типа, но которые при передаче их операциям кластера в качестве аргумента имели бы другое, чем ожидается, пред­ставление, что приводило бы к всевозможным очень неприятным ошибкам. Поэтому, чтобы использование абстракций данных было выгодно, ограничение сферы применения операций up и down необходимо.

Как уже говорилось, если операция down используется внутри кластера, то она убирает заслонку и представление объекта ста­новится видимым. Однако это представление есть просто другой абстрактный объект, и он защищен заслонкой, сконструирован­ной его собственной реализацией, которая может быть либо оп­ределенным пользователем кластером, либо частью реализации языка CLU. Реальное представление объекта снова недоступно, но информация об объекте может быть получена при помощи операций. Так, внутри кластера intset нам недоступна внутрен­няя структура массива, который реализует intset, но мы можем исследовать и изменять интересующую нас информацию, исполь­зуя операции работы с массивом.

Для операций up и down (и следовательно, для cvt) не гене­рируется никакого объектного кода. Они лишь информируют компилятор о том, что способ рассмотрения объекта изменился. Компилятор использует эту информацию для контроля типов. Так как контроль типов производится во время компиляции, эта информация не нужна при выполнении, хотя она и может быть по­лезна для отладки.

4.3. Использование абстракций данных

Если абстракция данных определена, то она не отличается от встроенных типов и ее объекты и операции должны использо­ваться точно так же, как объекты и операции встроенных типов. Насколько это возможно, зависит от используемого языка про­граммирования. В языке CLU могут быть объявлены переменные нового типа. Как, например, i: intset. Создавать объекты и мани­пулировать ими можно следующим образом;

ii = intset$create ( ) intset$insert (i, 3)

На рис. 4.6 представлена спецификация и реализация про­цедуры remove_dupls. Эта реализация использует тип данных intset для запоминания уже имеющихся в массиве элементов. Определенные пользователем типы могут также использо­ваться для представления других определяемых пользователем типов. Например, если мы собираемся реализовать для банков­ской системы тип данных account (счет), то может оказаться по-

Абстракции данных

femove_dupls=proc(a: array int])

modifies a

effects Удаляет из а все дубли элементов. Нижняя граница а остается той же самой, но расположение оставшихся элементов может изме­ниться. Например, если до обращения а = [1: 3, 13, 3, 6], то при возврате а имеет нижнюю границу 1 и содержит три элемента 3, 13 и 6, расположенных некоторым образом.

ai = array [int] remove_dupls = proc (a: ai) a_low: int :== ai$low (a) i: int : = a_low j: int: = a_low s: intset := intset$create () while i (= ai$high (a) do if— intset$mernber (s, a [i])

then intset$insert (s, a [i]) % a [i] не дубль. Оставить его, a [j] := a [i]

j:-j+i end i:=i+ I end

ai$trim (a, a_low, j — a_low) % удалить остальные элементы a end remove_dupls

Рис, 4.6. Использование типа данных intset.

лезным отслеживать индивидуальные вклады (deposits), снятия (withdrawls) и совокупный баланс (balance). Таким образом, мы можем иметь

гер == record [balance: int, deposits, withdrawls: intset ]

Здесь мы используем тип данных intset для представления счетов.

Соседние файлы в папке POSIBNIK