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

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, —благоприятный побочный эффект. Такие побочные эф­фекты часто используются для улучшения эффективности. Они возможны, если функция абстракции отображает различные эле­менты в один, так как тогда имеется много объектов представле­ния, которые представляют один и тот же абстрактный объект. Иногда полезно внутри реализации переходить от одного такого объекта представления к другому. Такой переход законен, так как новое представление соответствует тому же самому абстракт­ному объекту.

Соседние файлы в папке Б. Лисков