Константы с манифестом для этого непригодны

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

 

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

 

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 могут потребоваться и другие родители.

 

Константы пользовательских классов

 

Символические константы полезны не только при работе с предопределенными типами, такими как INTEGER . Они нужны и тогда, когда их значениями являются объекты классов, созданных разработчиком. В этом случае решение не столь очевидно.

 

 

Первым примером служит класс, описывающий комплексное число:

 

class COMPLEX creation

make_cartesian, make_polar

feature

x, y: REAL

-- Действительная и мнимая часть

make_cartesian (a, b: REAL) is

-- Установить действительную часть a, мнимую - b.

do

x := a; y := b

end

... Прочие методы (помимо x и y, других атрибутов нет) ...

end

 

 

Пусть мы хотим определить константу - комплексное число i , действительная часть которого равна 0 , а мнимая 1 . Первое, что приходит в голову, - это буквальная константа вида

 

i: COMPLEX is "Выражение, определяющее комплексное число (0, 1)"

 

 

Как записать выражение после is ? Для пользовательских типов данных никакой формы записи неименованных констант не существует.

Можно представить себе вариант нотации на основе атрибутов класса:

 

i: COMPLEX is COMPLEX (0, 1)

 

 

Но этот подход, хотя и реализован в некоторых ОО-языках, противоречит принципу модульности - основе объектной методологии. Приняв этот подход, мы согласились бы с тем, что клиенты COMPLEX должны описывать константы в терминах реализации класса, а это нарушает принцип Скрытия информации.

Кроме того, как гарантировать соответствие неименованной константы инварианту класса, если таковой имеется?

Последнее замечание позволяет найти правильное решение. Мы уже говорили о том, что в момент рождения объекта ответственность за соблюдение инварианта возлагается на процедуру создания . Создание объекта иным путем (помимо безопасного клонирования clone ) ведет к ситуациям ошибки. Поэтому мы должны найти путь, основанный на обычном методе создания объектов класса.