
- •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.Упорядоченные списки
4.6.3.Сохранение инварианта представления
Для того чтобы продемонстрировать корректность реализации типа, мы должны, в частности, показать, что инвариант представления сохраняется для всех законных объектов представления. Мы можем сделать это следующим образом. Прежде всего мы покажем, что инвариант сохраняется для объектов, возвращаемых операциями (как, например, операциейpoly$create), которые возвращают объект типа, но не имеют аргументов типа. Для всех других операций мы можем предположить, что при их вызове инвариант сохраняется для всех аргументов, являющихся объектами типа; тогда мы должны показать, что он сохраняется при возврате как для аргументов типа, так и для возвращаемых объектов типа.
Например, реализация набора intset(рис. 4.5)имеет инвариант
%Для всех целых i, j,таких, чтоlow (r) i <jbigh(r)%r[i]~=rlj]
Операцияintset$createотвечает этому инварианту потому, что заново созданный массив пуст. Операцияmemberтакже сохраняет этот инвариант, так как мы знаем, что инвариант сохраняется для аргументаsи что эта операция не модифицируетs. Операцияinsertтакже сохраняет инвариант, так как
1)инвариант сохраняется для ее аргумента sпри обращении;
2)при вызове операцииmemberиз операцииinsertинвариант сохраняется потому, что он сохраняется в операцииmember; и
3)операцияinsertдобавляет х к s,только если выражение ^member (s,х) имеет значениеtrue; следовательно, так как набор sудовлетворяет инварианту при вызове, он также удовлетворяет инварианту после добавления к нему х.
В качестве второго примера рассмотрим реализацию полиномовpoly, представленную на рис. 4.7.Вспомним, что инвариант есть
% low (r) Ss О
% & if empty (s) then high (r) == 0 % else г How (r) ] ~ = 0 & г [high (г) I ~ == 0
Операция poly$createсохраняет инвариант потому, что она создает нулевой полином. Операцияmillсохраняет инвариант потому, что
1)при вызове инвариант сохраняется для р иq;
2)случай, когда р или q —нулевой полином, распознается и создается соответствующее представление; и
3)в противном случае ни р, ни qне содержат нулей ни в старшем, ни в младшем члене; следовательно, ни младший элемент возвращаемого массива (bottom(р)*bottom (q)),ни старший элемент (top(р)*top (q))не может быть нулем.
Здесь мы предполагаем, что абстрактные объекты нельзя модифицировать вне их реализации. Если это возможно, то мы не можем предполагать, что инвариант сохраняется при вызове операции, так как какие-то модули могут его изменить.
4.5.4.Изменяемые представления
Изменяемость (или неизменяемость) —это свойство абстракции, которое должно сохраняться реализацией. Изменяемые абстракции должны иметь изменяемые представления, иначе будет невозможно обеспечить требуемую изменяемость. Однако неизменяемые абстракции не обязательно должны иметь неизменяемые представления. Например, полиномы неизменяемы, но имеют изменяемое представление. Изменяемые представления приемлемы, если модификации, сделанные в представлении, не могут быть замечены пользователями абстракций.
Иногда полезно создавать объект, изменяя его представление, однако, когда объект создан, его представление больше не модифицируется. Так, например, созданы полиномы. Изменяемость также полезна дляблагоприятных побочных эффектов,являющихся модификациями, которые не видны вне реализации. Например, давайте представим рациональное число парой целых:
гер =•recordlnum,denom:int]
Функция абстракции есть
%типичное рациональное число естьn/d%Функция абстракции есть%А (г) =r.num/r.denom
Исходя из этого представления, мы должны принять несколько решений: что делать с нулевым знаменателем, как хранить отрицательные рациональные числа и хранить ли рациональные числа в сокращенной форме (т. е. когда числитель и знаменатель не имеют общего делителя). Мы решаем: исключить нулевой знаменатель, представлять отрицательные рациональные числа с помощью отрицательного числителя инехранить представления в сокращенной форме (для ускорения таких операций, как умножение). Таким образом, имеем
%Инвариант представления есть%r.denom >О
Давайте также решим находить сокращенную форму при проверке двух рациональных чисел на равенство. Это мы можем сделать, используя процедуруgcd.
gcd = proc(n,d:int) returns(int)requiresnиdдолжны быть положительнымиeffectsВозвращает макс. общий делитель nи d.
Реализация операции equalпредставлена на рис. 4.9.Однажды найденные, сокращенные формы записываются в представление, так как это ускоряет работу при последующих обращениях к операцииequal.
rep == record [nurn, denom: int] equal == proc (rl, r2: cvt) returns (bool) if rl.nurn =: 0 then return (r2.niim = 0) elseif r2.niim == 0 then return (false) end reduce (rl) reduce (r2)
return (rl.num == r2.num cand rl.denom = r2.denom) end equal
%reduce —внутренняя программа, приводящая ее аргумент к сокращенной
% форме reduce proc (r: rep) g: int :== gcd (in1$abs (r.num), r.denom) r.num :== r.num/g r.denom := r.denom/g etid reduce Рис, 4.9. Благоприятный побочный эффект.
Модификация представления, осуществляемая операцией equal, —благоприятный побочный эффект. Такие побочные эффекты часто используются для улучшения эффективности. Они возможны, если функция абстракции отображает различные элементы в один, так как тогда имеется много объектов представления, которые представляют один и тот же абстрактный объект. Иногда полезно внутри реализации переходить от одного такого объекта представления к другому. Такой переход законен, так как новое представление соответствует тому же самому абстрактному объекту.