Основы объектно-ориентированного проектирования


Скрытие представления: частная история


Пакет STACKS в том виде, как он задан, не реализует принцип скрытия информации. Объявления типов STACK и STACK_CONTENTS, находясь в интерфейсе, позволяют клиентам непосредственный доступ к представлению стеков. Например, клиент может включить код вида:

[1] use REAL_STACKS_1;... s: STACK; ... s.implementation (3) := 7.0; s.last := 51;

грубо нарушая основную спецификацию абстрактных типов данных.

Концептуально объявления типа должны находиться в теле. Почему их туда не помещают с самого начала? Объяснение находится вне языка и требует рассмотрения проблем программного окружения.

Одно из уже упомянутых требований к языку Ada состояло в возможности независимой компиляции пакета при наличии доступа к его интерфейсу, но необязательно к его телу. Принятая технология предполагала построение сверху вниз: для продолжения работы над модулем достаточно знать спецификацию необходимых ему средств. Действительная реализация могла появиться значительно позже.

Если есть доступ к интерфейсу REAL_STACKS_1 (то есть к интерфейсу STACKS, REAL_STACKS_1 является просто его родовым порождением), можно компилировать любого из его клиентов. Такой клиент будет содержать объявления вида:

use REAL_STACKS_1;... s1, s2: STACK; ... s2 := s1;

Компилятор не сможет их хорошо обрабатывать, не зная размера объекта типа STACK. Но это может определяться только из объявлений типа для STACK и вспомогательного типа STACK_CONTENTS.

Отсюда концептуальная дилемма, стоявшая перед проектировщиками языка Ada: вопросы реализации требуют помещения объявлений типа в рай - интерфейс, в то время как им место в аду - теле пакета.

Пришлось создать чистилище: специальный раздел пакета, физически видимый в интерфейсе и компилируемый с ним, но такой, что клиенты не могут обращаться к его элементам. Чистилище - это закрытая часть интерфейса, она вводится ключевым словом private. Любое объявление, появляющееся здесь, недоступно клиентам. Эта схема иллюстрируется нашей последней версией интерфейса пакета, задающего стек:

generic type G is private; package STACKS is type STACK (capacity: POSITIVE) is private; procedure put (x: in G; s: in out STACK); procedure remove (s: in out STACK); function item (s: STACK) return G; function empty (s: STACK) return BOOLEAN; Overflow, Underflow: EXCEPTION; private type STACK_VALUES is array (POSITIVE range <>) of G; type STACK (capacity: POSITIVE) is record implementation: STACK_VALUES (1..capacity); count: NATURAL := 0; end record end STACKS;

Отметим, тип STACK теперь должен объявляться дважды: сначала в открытой части интерфейса, где он специфицируется как private, затем еще раз в закрытой части, где дается полное описание.


Начало  Назад  Вперед



Книжный магазин