Опубликован: 17.10.2005 | Уровень: специалист | Доступ: свободно
Лекция 18:

Глобальные объекты и константы

< Лекция 17 || Лекция 18: 123456
Аннотация: Локальных знаний не достаточно - компонентам ПО необходима глобальная информация: разделяемые данные, общее окно для вывода ошибок, шлюз для подключения к базе данных или сети. В классическом подходе достаточно объявить такой объект глобальной переменной главной программы. В ОО-системах нет ни главной программы, ни глобальных переменных. Но разделяемые (shared) объекты по-прежнему нужны.

Глобальные объекты - некий вызов ОО-методу, провозглашающему идеи децентрализации, модульности и автономности. Борьба шла за независимость модулей, за избавление от произвола центральной власти. Теперь этой власти нет. Как же построить систему, в которой компоненты совместно используют данные, не теряя своей автономности, гибкости, допускают повторное использование?

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

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

Константы базовых типов

Начнем с формы записи констант.

Правило стиля - принцип символических констант - гласит, что обращение к конкретному значению (числу, символу или строке) почти всегда должно быть косвенным. Должно существовать определение константы, задающее имя, играющее роль символической константы ( symbolic constant), и связанное с ним значение - константа, называемая манифестной ( manifest constant). Далее в алгоритме следует использовать символическую константу. Тому есть два объяснения.

  • Читабельность: читающему текст легче понять смысл US_states_count, чем числа 50 ;
  • Расширяемость: символическую константу легко обновить, исправив лишь ее определение.

Принцип допускает применение манифестных или, как часто говорят, неименованных констант в качестве "начальных" элементов разнообразных операций, как в случае с циклом from i = 1 until i > n (Но n, конечно, должно быть символической константой).

Итак, нам нужен простой и ясный способ определения символических констант.

Атрибуты-константы

Как и все сущности, символические константы должны быть определены внутри класса. Будем рассматривать константы как атрибуты с фиксированным значением, одинаковым для всех экземпляров класса.

Синтаксически вновь используем служебное слово is, применяемое при описании методов, только здесь за ним будет следовать не алгоритм, а значение нужного типа. Вот примеры определения констант базовых типов INTEGER, BOOLEAN, REAL и CHARACTER:

Zero: INTEGER is 0
Ok: BOOLEAN is True
Pi: REAL is 3.1415926524
Backslash: CHARACTER is '\'

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

Потомки не могут переопределять значения атрибутов-констант.

Как и другие атрибуты, класс может экспортировать константы или скрывать. Так, если C - класс, экспортирующий выше объявленные константы, а у клиента класса к сущности x присоединен объект типа C, то выражение x.Backslash обозначает символ '\'.

В отличие от атрибутов-переменных, константы не занимают в памяти места. Их введение не связано с издержками в период выполнения, а потому не страшно, если их в классе достаточно много.

Использование констант

Вот пример, показывающий, как клиент может применять константы, определенные в классе:

class FILE feature
         error_code: INTEGER;         -- Атрибут-переменная
         Ok: INTEGER is 0
         Open_error: INTEGER is 1
         ...
         open (file_name: STRING) is
                          -- Открыть файл с именем file_name
                          -- и связать его с текущим файловым объектом
         do
                 error_code := Ok
...
                 if "Что-то не так" then
                           error_code := Open_error
                 end
         end
         ... Прочие компоненты ...
end

Клиент может вызвать метод open и проверить успешность операции:

f: FILE; ...
f.open
if f.error_code = f.Open_error then
         "Принять меры"
else
         ...
end

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

class EDITOR_CONSTANTS
feature
         Insert: CHARACTER is 'i'
         Delete: CHARACTER is 'd'; -- и т.д.
         ...
end
class SOME_CLASS_FOR_THE_EDITOR
inherit
         EDITOR_CONSTANTS
         ...Другие возможные родители ...
feature ...
... подпрограммы класса имеют доступ к константам, описанным в EDITOR_CONSTANTS ...
end

Класс, подобный EDITOR_CONSTANTS, служит лишь для размещения в нем группы констант, и его роль как "реализации АТД" (а это - наше рабочее определение класса) не столь очевидна, как в предыдущих примерах. Теоретическое обоснование введения таких классов мы обсудим позднее. Представленная схема работоспособна только при множественном наследовании, поскольку классу SOME_CLASS_FOR_THE_EDITOR могут потребоваться и другие родители.

< Лекция 17 || Лекция 18: 123456
Александр Шалухо
Александр Шалухо
Как сбросить прогресс по курсу? Хочу начать заново
Анатолий Садков
Анатолий Садков
Вопросик
Даниил Цветков
Даниил Цветков
Россия, г. Мурманск
Софья Медведева
Софья Медведева
Россия, Город Мурманск