Чтение онлайн

ЖАНРЫ

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

Мейер Бертран

Шрифт:

i := a.lower

invariant

– - Для всех элементов из интервала [a.lower .. i - 1], (a @ i) /= x

variant

a.upper - i

until

i > a.upper or else (a @ i = x)

loop

i := i + 1

end;

Result := (i <= a.upper)

Цель - сделать Result верным, если и только если значение x находится в массиве a. Использование or здесь будет неверным. В этом случае всегда могут вычисляться два операнда, так что при истинности первого операнда (i > a.upper) произойдет попытка доступа к несуществующему элементу массива a @(aupper+1), что приведет к ошибке во время выполнения (нарушение предусловия при включенной проверке утверждений).

Решение без нестрогих операторов будет неэлегантным.

Другой пример - утверждение, например, инварианта класса, выражающее, что первое значение списка l целых неотрицательно, при условии, что список непустой:

l.empty or else l.first >= 0

При использовании or инвариант был бы некорректен. Здесь нет способа написать условие без нестрогих операторов (кроме написания специальной функции и вызова ее в утверждении). Базовые библиотеки алгоритмов и структур данных содержат много таких случаев.

Оператор implies, описывающий включения, также нестрогий. Форма implies менее привычна, но часто более ясна, например, последний пример выглядит лучше в записи:

(not l.empty) implies (l.first >= 0)

Строки

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

Строковая константа записывается в двойных кавычках, например,

"ABcd Ef ~*_ 01"

Символ двойных кавычек должны предваряться знаком %, если он появляется как один из символов строки.

Неконстантные строки также являются экземплярами класса STRING, чья процедура создания make принимает в качестве аргумента ожидаемую начальную длину строки, так что

text1, text2: STRING; n: INTEGER;

...

create text1.make (n)

динамически размещает строку text1, резервируя пространство для n символов. Заметим, что n– только исходный размер, не максимальный. Любая строка может увеличиваться и сжиматься до произвольного размера.

На экземплярах STRING доступны многочисленные операции: сцепление, выделение символов и подстрок, сравнение и т.д. (Они могут изменять размер строки, автоматически запуская повторное размещение, если размер строки становится больше текущего.)

Присваивание строк означает разделение (sharing): после text2 := text1, любая модификация text1 модифицирует text2, и наоборот. Для получения копии строки, а не копии ссылки, используется клонирование text2 := clone (text1).

Константную строку можно объявить как атрибут:

message: STRING is "Your message here"

Ввод и вывод

Два класса библиотеки KERNEL обеспечивают основные средства ввода и вывода: FILE и STD_FILES.

Среди операций, определенных для объекта f типа FILE, есть следующие:

create f.make ("name") -- Связывает f с файлом по имени name.

f.open_write -- Открытие f для записи

f.open_read -- Открытие f для чтения

f.put_string ("A_STRING") -- Запись данной строки в файл f

Операции ввода-вывода стандартных файлов ввода, вывода и ошибок, можно наследовать из класса STD_FILES, определяющего компоненты input, output и error. В качестве альтернативы можно использовать предопределенное значение io, как в io.put_string ("ABC"), обходя наследование.

Лексические соглашения

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

Регистр в идентификаторах не учитывается, так что Hi, hi, HI и hI– все означают один и тот же идентификатор. Было бы опасным позволять двум идентификаторам, различающимся только одним символом, скажем Structure и structure, обозначать различные элементы. Лучше попросить разработчиков включить воображение, чем рисковать возникновением ошибок.

Нотация включает набор точных стандартных соглашений по стилю (см. лекцию 26 курса "Основы объектно-ориентированного проектирования"): имена классов (INTEGER, POINT ...) и формальные родовые параметры (G в LIST [G]) записываются в верхнем регистре; предопределенные сущности и выражения (Result, Current...) и константные атрибуты (Pi) начинаются с буквы верхнего регистра и продолжаются в нижнем регистре. Все другие идентификаторы (неконстантные атрибуты, формальные аргументы программ, локальные сущности) - в нижнем регистре. Хотя компиляторы не проверяют эти соглашения, не являющиеся частью спецификации, они важны для удобочитаемости текстов программных продуктов и последовательно применяются в библиотеках и текстах этой книги.

Ключевые концепции

[x]. Внешние программы доступны через хорошо определенный интерфейс.

[x]. Объектная технология может служить в качестве механизма упаковки наследуемого ПО.

[x]. Подпрограммы не могут модифицировать свои аргументы, хотя они могут изменять объекты, связанные с этими аргументами.

[x]. Нотация включает небольшой набор инструкций: присваивания, выбора, цикла, вызова, отладки и проверки.

Поделиться с друзьями: