Опубликован: 17.10.2005 | Доступ: свободный | Студентов: 8823 / 588 | Оценка: 4.38 / 4.10 | Длительность: 41:16:00
ISBN: 978-5-7502-0255-3
Специальности: Программист
Лекция 7:

Статические структуры: классы

Селективный экспорт и скрытие информации

До сих пор все компоненты класса были доступны всем потенциальным клиентам. Это, безусловно, не всегда приемлемо, поскольку скрытие информации является важным элементом построения последовательной и гибкой архитектуры.

Рассмотрим способы скрытия компонент от всех или некоторых клиентов. Данный раздел содержит лишь введение в нотацию - подробному рассмотрению интерфейсов классов посвящена одна из последующих лекций (лекция 5 курса "Основы объектно-ориентированного проектирования"). В примерах для простоты будут рассматриваться только именованные компоненты, однако все изложенные ниже соображения справедливы и для компонент-операций.

Неограниченный доступ

По умолчанию все компоненты доступны для всех клиентов. Для класса

class S1 feature
   f ...
   g ...
   ...
end

компоненты f, g, ... доступны всем клиентам S1. Это означает, что если в классе C объявлена сущность x класса S1, то вызов

x.f ...

является допустимым, если выполнены все другие условия корректности вызова f.

Ограничение доступа клиентам

Для ограничения доступа клиентов к некоторой компоненте h, будет использована возможность включения в объявление класса двух или более разделов feature. Объявление будет выглядеть следующим образом

class S2 feature
   f ...
   g ...
feature {A, B}
   h ...
   ...
end

Компоненты f и g по-прежнему доступны всем клиентам. Компонент h доступен только для классов A и B, а также их потомков (прямых или косвенных). Это означает, что для некоторого x типа S2 следующий вызов

x.h

является допустимым только в исходных текстах классов A, B или одного из их потомков.

В особом случае, когда необходимо скрыть компонент i от всех клиентов, можно объявить его экспортируемым пустому списку клиентов (Не рекомендуемый стиль (см. ниже S5).):

class S3 feature { }
   i ...
end

В этом случае любой вызов x.i(...) недопустим. Единственная возможность обращения к i - неквалифицированный вызов

i (...)

в тексте подпрограммы класса S3 или его потомков. Такой механизм обеспечивает полное скрытие информации.

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

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

Стиль объявления скрытых компонент

Использованный выше стиль объявления скрытой компоненты i не слишком удачен. Это хорошо видно в следующем примере (Не рекомендуемый стиль (см. ниже S5).)

class S4 feature
   exported ...
feature {}
   secret ...
end

где secret является скрытой компонентой, а exported - общедоступной. Разница в написании feature {} с пустым списком в скобках и feature без всяких скобок едва заметна. Гораздо разумнее вместо пустого использовать список, содержащий единственный класс NONE (Рекомендуемый стиль.)

class S5 feature
   ... exported ...
feature {NONE}
   ... secret ...
end

Класс NONE является базовым библиотечным классом и обсуждается далее в связи с наследованием. По определению он не может иметь потомков и нельзя создать его экземпляр. Таким образом, компонент, экспортированный классу NONE, фактически является скрытым. Между объявлениями S4 и S5 нет принципиальной разницы, однако во втором случае исходный текст становится более понятным и удобочитаемым. Именно такой стиль объявления скрытых компонент будет использоваться далее в этой книге.

"Внутренний" экспорт

Рассмотрим объявление класса

indexing
   замечание: "Ошибочное объявление (объяснение см. ниже)"
class S6 feature
   x: S6
   my_routine is do ... print (x.secret) ... end
feature {NONE}
   secret: INTEGER
end -- class S6

Наличие в объявлении класса атрибута x типа S6 и вызова x.secret делает его собственным клиентом. Но такой вызов недопустим, так как компонент secret скрыт от всех клиентов! Тот факт, что неавторизованным клиентом является сам класс S6, нечего не меняет - объявленный статус secret делает недопустимым любой вызов вида x.secret. Всякие исключения нарушают простоту сформулированного правила.

Есть простое решение: написать вместо feature {NONE} предложение feature {S6} , экспортируя компоненту самому себе и своим потомкам.

Необходимо отметить, что подобный прием необходим, только если в тексте класса присутствует квалифицированный вызов аналогичный print (x.secret). Очевидно, что неквалифицированный вызов secret в инструкции print (secret) допустим без дополнительных ухищрений. Все компоненты, объявленные в данном классе, могут использоваться в подпрограммах данного класса и его потомков. Только при наличии квалифицированных вызовов приходится экспортировать компонент самому себе.

Александр Шалухо
Александр Шалухо
Анатолий Садков
Анатолий Садков

При заказе pdf документа с сертификатом будет отправлен только сертификат или что-то ещё?