- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Основы объектно-ориентированного программирования - Бертран Мейер
Шрифт:
Интервал:
Закладка:
Как уже говорилось, ни один модуль не имеет больше прав на разделяемые данные, чем остальные. Это особенно справедливо для только что рассмотренных случаев. Если расчет значения способен инициировать любой модуль, нет смысла и говорить о том, будто один из них выступает в роли владельца. Такое положение дел и отражает модульная структура системы.
Однократные процедуры
Функция close должна вызываться только один раз. Контроль над количеством ее вызовов рекомендуется возложить на глобальную переменную приложения.
Из руководства к коммерческой библиотеке функций языка C
Механизм однократных функций интересен и при работе с процедурами. Однократные процедуры могут применяться для инициализации общесистемного свойства, когда заранее неизвестно, какому компоненту это свойство понадобится первому.
Примером может стать графическая библиотека, в которой любая функция, вызываемая первой, должна предварительно провести настройку, учитывающую параметры дисплея. Автор библиотеки мог, конечно, потребовать, чтобы каждый клиент начинал работу с библиотекой с вызова функции настройки. Этот нюанс, в сущности, не решает проблему - чтобы справиться с ошибками, любая функция должна обнаруживать, не запущена ли она без настройки. Но если функции такие "умные", то зачем что-то требовать от клиента, когда можно нужную функцию настройки вызывать самостоятельно.
Однократные процедуры решают эту проблему лучше:
check_setup is
-- Настроить терминал, если это еще не сделано.
once
terminal_setup -- Фактические действия по настройке.
end
Теперь каждая экранная функция должна начинаться с обращения к check_setup, первый вызов которой приведет к настройке параметров, а остальные не сделают ничего. Заметьте, что check_setup не должна экспортироваться клиентам.
Однократная процедура - это важный прием, упрощающий применение библиотек и других программных пакетов.
Параметры
Однократные процедуры и функции могут иметь параметры, необходимые, по определению, лишь при первом вызове.
Однократные функции, закрепление и универсальность
В этом разделе мы обсудим конкретную техническую проблему, поэтому при первом чтении книги его можно пропустить.
Однократные функции, тип которых не является встроенным, вносят потенциальную несовместимость с механизмом закрепления типов и универсальностью.
Начнем с универсальности. Пусть в родовом классе EXAMPLE [G] есть однократная функция, чей тип родовой параметр:
f: G is once ... end
Рассмотрим пример ее использования:
character_example: EXAMPLE [CHARACTER]
...
print (character_example.f)
Пока все в порядке. Но если попытаться получить константу с другим родовым параметром:
integer_example: EXAMPLE [INTEGER]
...
print (integer_example.f + 1)
В последней инструкции мы складываем два числа. Первое значение, результат вызова f, к сожалению, уже найдено, поскольку f - однократная функция, причем символьного, а не числового типа. Сложение окажется недопустимым.
Проблема заключается в попытке разделения значения разными формами родового порождения, ожидающими значения, тип которого определяется родовым параметром. Аналогичная ситуация возникает и с закреплением типов. Представим себе класс B, добавляющий еще один атрибут к компонентам своего родителя A:
class B inherit A feature
attribute_of_B: INTEGER
end
Пусть A имеет однократную функцию f, возвращающую результат закрепленного типа:
f: like Current is once create Result make end
и пусть первый вызов функции f имеет вид:
a2 := a1.f
где a1 и a2 имеют тип A. Вычисление f создаст экземпляр A и присоединит его к сущности a2. Все прекрасно. Но предположим, далее следует:
b2 := b1.f
где b1 и b2 имеют тип B. Не будь f однократной функцией, никакой проблемы бы не возникло. Вызов f породил бы экземпляр класса B и вернул его в качестве результата. Но функция является однократной, а ее результат был уже найден при первом вызове. И это - экземпляр A, но не B. Поэтому инструкция вида:
print (b2.attribute_of_B)
попытается обратиться к несуществующему полю объекта A.
Проблема в том, что закрепление вызывает неявное переопределение типов. Если бы f была переопределена явно, с применением в классе B объявления
f: B is once create Resultl make end
при условии, что исходный вариант f в классе A возвращает результат типа A (а не like Current), все было бы замечательно: экземпляры A обращались бы к версии f для A, экземпляры B - к версии f для B. Однако закрепление типов было введено как раз для того, чтобы избавить нас от таких явных переопределений.
Эти примеры - свидетельства несовместимости семантики однократных функций (с процедурами все прекрасно) с результатами применения закрепленных типов и формальных родовых параметров. Одно из решений проблемы в том, чтобы трактовать такие случаи как явные переопределения, приняв за правило то, что результат однократной функции совместно используется лишь в пределах одной формы родовой порождения, а при закреплении результата - лишь среди экземпляров своего класса. Недостатком такого подхода, впрочем, является, что он не отвечает интуитивной семантике однократных функций, которые, с позиции клиента, должны быть эквивалентны разделяемым атрибутам. Во избежание недоразумений и возможных ошибок можно пойти на более суровые меры, наложив полный запрет на сценарии подобного рода:
Правило для однократной функции
Тип результата однократной функции не может быть закреплен и не может включать любой родовой параметр.
Константы строковых типов
В начале этой лекции были введены символьные константы, значением которых является символ. Например:
Backslash: CHARACTER is ''
Однако нередко классам требуются строковые константы, использующие, как обычно, для записи константы двойные кавычки:
[S1]
Message: STRING is "Syntax error" -- "Синтаксическая ошибка"
Вспомните, что STRING - не простой тип. Это - библиотечный класс, поэтому значение, связанное с сущностью Message во время работы программы, является объектом, то есть экземпляром STRING. Как вы могли догадаться, такое описание является сокращенной формой объявления однократной функции вида:
[S2]
Message: STRING is
-- Строка из 12 символов
once
create Result.make (12)
Result.put ('S', 1)
Result.put ('y', 2)
...
Result.put ('r', 12)
end
Строковые значения являются не константами, а ссылками на разделяемые объекты. Любой класс, имеющий доступ к Message, может изменить значение одного или нескольких символов строки. Строковые константы можно использовать и как выражения при передаче параметров или присваивании:
Message_window.display ("НАЖМИТЕ ЛЕВУЮ КНОПКУ ДЛЯ ВЫХОДА")
greeting := "Привет!"
Unique-значения
Иногда при разработке программ возникает потребность в сущности, принимающей лишь несколько значений, характеризующих возможные ситуации. Так, операция чтения может вернуть код результата, значениями которого будут признаки успешной операции, ошибки при открытии и ошибки при считывании. Простым решением проблемы было бы применение целочисленного атрибута:
code: INTEGER
и набора символьных констант
[U1]
Successful: INTEGER is 1
Open_error: INTEGER is 2
Read_error: INTEGER is 3
которые позволяют записывать условные инструкции вида
[U2]
if code = Successful then ...
