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

4.5.2.Инвариант представления

В ориентированных на работу с типами языках (как, например, в языке CLLJ)контроль типов гарантирует, что если абстрактный объект типа передается как аргумент операции типа, то этот аб­страктный объект представляется объектом типа представления. Во многих случаях, однако, не все объекты представления яв­ляются законными представлениями абстрактных объектов. На­пример, для кластера intset(рис. 4.5)каждый массив независимо от значений является элементомЯ',например, массивы [1: 1, 7,6], [1: 1, 6, 6]и [1:6, 1,7].Однако в реализации intsetмы ре­шили, что каждый элемент набора записывается в массив только один раз. Следовательно, законные представления наборов int­setв этом кластере не содержат дублирующих друг друга элемен­тов; [1: 1, 6, 6],например —незаконное представление.

Условие, которому удовлетворяют все законные объекты, называется инвариантом представления.Инвариант представле­ния 1есть предикат

1: rep

bool.

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

i < j ^ high (r)

который принимает значение trueдля законных объектов пред­ставления. Например, для кластера intsetмы можем дать следую­щий инвариант представления:

%Инвариант представления есть%Для всех целых i, j,таких, что low (r): о/о r [i]~=r [j]

Заметим, что для массива II: 1, 6, 6] 1принимает значениеfalse,а для массивов [1: 1, 7, 6]и [1: 6, 1, 7]—значение true. Заметим также, что мы не включаем в 1условия, которые прини­мают значение trueдля всех массивов (например, size (r) == = high (r) — low (r) + 1),потому что это гарантируется про­цедурами работы с массивами и соответственно предполагается в реализации intset.

В качестве второго примера инварианта представления рас­смотрим альтернативное представление наборов intset,состоя­щее из булева массива размерности 100и массива целых:

гер = record leis: array [bool], other.els: array tint], size: int]

Идея заключается в том, что для целых от 1до 100мы отме­чаем их принадлежность набору, записывая значение trueвr.els ti 1.Не принадлежащие этому диапазону целые записываются в other.elsточно так же, как в нашей предыдущей реализацииintset.Так как невыгодно вычислять размер набора intset,про­сматривая все элементы массива els,мы записываем этот размер в представление в явном виде. Это представление хорошо, если почти все члены набора принадлежат диапазону 1—100.(В про­тивном случае пространство, требующееся для массива els,будет использоваться неэффективно.) Таким образом, мы имеем

%Функция абстракции есть о/о А (r) = {i-.other-els [i ] I low (r. other- els) ^ i s$ high (r.other, els)}

% U % {j U^js5 100 & r'els [j])

Здесь Uобозначает математическое объединение двух набо­ров. Итак,

%Инвариант представления есть% size (r.els) = 100 & low (r.els) = I % &все элементы r.otherне принадлежат диапазону I—100 % &в r.otherнет дубликатов элементов% & r.size = size (r.other, els) -(-%(число элем. со знач. trueв r.els)

Заметим, что поле sizeв этом представлении излишне: оно со­держит информацию, которая может быть получена из остальной части представления путем вычислений. Но, поскольку такая из­лишняя информация все же содержится в представлении, взаимо­связь этой информации с остальной частью представления должна быть объяснена в инварианте представления (например, послед­няя строка нашего инварианта представления).

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

% r.size= size (r.othei_els)+ cnt (r.els, low(т.els)) %где cnt (a, i) = if i »> high (a) then 0 % else if r [i] then I+cnt (a, i+1) % else cnt (a, i + 1)

Вспомогательная функция cntопределена здесь рекурсивно. Интересный инвариант представления имеет реализация поли­номов poly,представленная на рис. 4.7.Вспомним, что мы ре­шили не записывать нулевые коэффициенты справа и слева от значащих членов полинома и представлять нулевой полином пу­стым массивом. Следовательно, мы предполагаем, что старший и младший элементы массива —не нули. Кроме того, эти массивы всегда имеют неотрицательную нижнюю границу. И наконец, пустой массив (представляющий пустой полином) должен иметь верхнюю границу, равную нулю. Таким образом, мы имеем

%Инвариант представления есть% low (r) ^.0

% & if empty(т) then high (r) = 0 % else r (low (r) ]~=0 &r [high (r)] ~=0

Вспомним, что реализация операции degreeпредполагает, что верхняя граница массива равна степени полинома. Теперь мы видим это требование в инварианте представления.

Иногда все объекты представления законны. Тогда мы просто имеем

%Инвариант представления есть% true

Инвариант представления должен быть явно задан также и в этом случае. Он освобождает осуществляющего реализацию от возможной зависимости от какого-то более сильного инварианта.

Инвариант представления —это «инвариант» потому, что он всегда сохраняется для представлений абстрактных объектов, т. е. он сохраняется, если объект используется вне его реализа­ции. Инвариант представления не должен, однако, обязательно сохраняться всегда: он может быть нарушен при выполнении од­ной из операций типа. Например, операция poly$addможет по­лучить массив с нулевым старшим и младшим элементом, но такие элементы удаляются из массива перед возвратом из операции add. Инвариант представления должен сохраняться при возврате из операций.

Между функцией абстракции и инвариантом представления имеется определенная взаимосвязь. Функция абстракции имеет смысл только для законных представлений, так как только они представляют абстрактные объекты. Следовательно, нет необ­ходимости определять ее для незаконных представлений. Например, как мы упоминали раньше, функция абстракции для поли­номов имеет некую область определения —она определена только в случае, если массив имеет неотрицательную нижнюю границу. Этому требованию удовлетворяют все законные представления полиномов, что отражено в инварианте представления.

Существует соглашениеотом, что должно быть отражено в инварианте представления. Инвариант представления должен отражать все требования, от которых зависят операции, но может не отражать дополнительные требования. Например, все кон­кретные объекты для реализации, представленной на рис. 4.5, имеют нижнюю границу, равную, 1,но от этого не зависит реали­зация никаких операций, поэтому нет необходимости отражать это в инварианте представления. Хорошо представлять себе, что операции реализуют различные люди, которые не общаются друг с другом. Тогда понятно, что инвариант представления дол­жен содержать все требования, которые необходимо знать этим различным людям.

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

Все операции должны реализовываться с учетом инварианта представления. Например, предположим, что мы реализуем опе­рацию insertтак:

insert == proc (s: cvt, x: inl) rep$addh (s, x) end insert

Эта реализация может создать объект с дублирующимися элементами. Если мы знаем, что инвариант представления за­прещает такие объекты, то эта реализация очевидно некорректна. Инвариант представления также полезен для того, кто изу­чает реализацию. Например, в альтернативной реализации набора intsetмы можем решить подвергать массив представления сортировке. В этом случае мы будем иметь

%Инвариант представления есть%Для всех i, j,таких, что low(г) sg; i < j ^ high (r) % r [i] <r [j]

Все операции тогда будут реализовываться иначе, чем на рис. 4.5.Инвариант представления говорит тому, кто изучает реализацию, почему операции реализованы именно так, как они реализованы.

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