- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Основы объектно-ориентированного программирования - Бертран Мейер
Шрифт:
Интервал:
Закладка:
indexing
...
class C creation
p1, p2, ...
feature
... Объявления компонент, включая реализацию процедур p1, p2, ...
end
Совет, отражающий стиль: в случае класса с единственной процедурой создания - для нее рекомендуется имя make. Для классов с двумя и более процедурами создания желателен префикс make_, за которым следует квалификатор, как в следующем примере POINT. (См. "Правильный выбор имен", лекция 8 курса "Основы объектно-ориентированного проектирования")Соответствующая инструкция создания в этих случаях имеет другую форму:
create x.p (...)
где p одна из процедур создания перечисленных в разделе creation, и в круглых скобках (...) перечисляются фактические аргументы p. Результатом является создание объекта с использованием значений по умолчанию, как и ранее, а затем вызов p с заданными аргументами. Такая инструкция является комбинацией инструкции создания и вызова процедуры и называется порождающим вызовом (creation call). (Оригинальная версия класса POINT приведена в лекции 7)
В качестве примера добавим две процедуры создания в класс POINT, что позволит клиентам при создании новой точки указывать ее начальные координаты - декартовы или полярные. Введем процедуры создания: make_cartesian и make_polar. Вот схема:
class POINT1 creation
make_cartesian, make_polar
feature
... Компоненты из предыдущей версии класса:
x, y, ro, theta, translate, scale, ...
feature {NONE} - Этот вариант экспорта рассмотрен ниже.
make_cartesian (a, b: REAL) is
-- Инициализация точки с декартовыми координатами a и b.
do
x := a; y := b
end
make_ polar (r, t: REAL) is
-- Инициализация точки с полярными координатами r и t.
do
x := r * cos (t); y := r * sin (t)
end
end
Для такого класса клиент будет создавать точки инструкциями вида:
create my_point.make_cartesian (0, 1)
create my_point.make_polar (1, Pi/2)
В обоих случаях создается точка с одинаковыми координатами в предположении, что константа Pi имеет общепринятый смысл. Вот правило, определяющее эффект порождающего вызова. Первые три пункта правила такие же, как и для базисной формы, приведенной ранее:
Эффект порождающего вызова
Рассмотрим порождающий вызов в форме create x.p(...).
Пусть тип цели x это ссылочный тип, основанный на классе C, p(...) - процедура создания класса C, с заданным списком фактических аргументов. Эффект вызова состоит в выполнении следующих четырех шагов:
[x]. (C1) Создание нового экземпляра C (набора полей, по одному на каждый атрибут C). Пусть OC - это новый экземпляр.
[x]. (C2) Инициализация каждого поля OC соответствующими стандартными значениями по умолчанию.
[x]. (C3) Присоединение значения x (ссылки) к OC.
[x]. (С4) Вызов процедуры p c заданными аргументами и с целевым объектом OC.
Статус экспорта процедур создания
Для двух процедур создания, объявленных в классе POINT1, предложение feature имело вид feature {NONE}. Это означает, что эти процедуры закрыты для обычных вызовов, но остаются открытыми для порождающих вызовов. Только что представленные два примера порождающих вызовов являются корректными, но нормальные вызовы, например my_point.make_cartesian (0, 1) или my_point.make_polar (1, Pi/2) некорректны, так как процедуры недоступны клиентам со статусом обычных компонентов.
Решение о закрытости процедур означает, что мы не хотим после создания точки дать возможность клиентам прямого доступа к изменению их координат, хотя они могут делать это через другие процедуры класса, например такие, как translate и scale . Конечно, это лишь одна из возможных политик, вполне разумно экспортировать процедуры создания клиентам, придавая им дополнительно статус обычных процедур.
Для процедур создания можно установить выборочный статус порождающего вызова. Для этого достаточно в предложении creation перечислить классы, которым разрешается создавать объекты:
class C creation {A, B, ...}
p1, p2,
...
Этот прием применяется значительно реже, чем задание статуса экспорта этих процедур как обычных компонентов класса в предложении feature. Важно помнить, что статус экспорта порождающего вызова и статус экспорта обычного вызова не зависят друг от друга, они устанавливаются независимо в разных предложениях.
Правила, применимые к процедурам создания
Две формы инструкций создания: create x и create x.p (...) , являются взаимно исключающими. Если в классе задано предложение creation , то допускается только порождающие вызовы, базовая форма создания считается в этом случае недопустимой и отвергается компилятором.
Это соглашение кажется на первый взгляд странным, но смысл его становится понятным при рассмотрении требований согласованности объекта. Объект - это не просто набор полей, это реализация АТД, так что поля его будут согласованы только если они удовлетворяют ограничениям, заданным спецификацией АТД. Вот типичный пример. Предположим, что объект задает некоторую личность с двумя полями - год рождения и возраст. Понятно, что согласованность этого объекта не допускает независимых значений этих полей, они связаны вполне определенным соотношением, которое может быть частью спецификации. Инструкция создания обязана всегда производить на свет согласованный объект. Базовая форма этой инструкции применима только в тех частных и довольно редких случаях, когда стратегия умолчания удовлетворяет требованиям согласованности. Во всех остальных случаях в классе требуется определять процедуры создания, что автоматически запрещает использование базовой инструкции создания.
В тех редких случаях, когда инициализация по умолчанию допустима, поскольку удовлетворяет инварианту класса, может появиться желание включить ее в состав процедур создания. Для этого необходимо в список процедур создания включить специальную процедуру, наследуемую от класса ANY, с именем nothing. Как следует из ее имени, эта процедура без аргументов ничего не делает, имея пустое тело. Вот пример подобного включения:
class C creation
nothing, some_creation_procedure, some_other_creation_procedure...
feature
...
Хотя по-прежнему базовая инструкция создания является некорректной в этом случае, но теперь клиент имеет возможность создать объект порождающим вызовом create x.nothing
В заключение обратите внимание на специальное правило - теперь появилась возможность определить класс, клиенты которого не смогут создавать экземпляры класса. Вот пример того, как этого можно добиться:
class C creation
-- Здесь ничего не указано!
feature
... Текст класса, как обычно ...
end
Класс имеет предложение creation , но пустое. Это означает согласно установленным правилам, что создавать объекты можно только с помощью процедур создания, которых нет, что означает невозможность создания объектов.
Если ограничиться ОО-механизмом, рассмотренным до сих пор, то такая возможность запрета на создание объектов класса кажется надуманной. Знакомство с наследованием придает ей смысл, - иногда желательно использовать класс только в интересах наследования. Эта цель и может быть достигнута таким способом. Заметьте, этого же можно добиться, сделав класс абстрактным (отложенным). Но в этом случае у класса должен быть, по крайней мере, один отложенный метод. Иногда разумно полностью определить методы, но не включить в класс процедуры создания.
Процедуры создания и перегрузка
В продолжение обсуждения полезно сравнить применяемый подход с несколькими процедурами создания с подходом, используемым в языках C++/Java. В этих языках применяется техника, основанная на перегрузке. Суть ее такова: все процедуры создания, называемые конструкторами, перегружены - они имеют одно и то же имя, совпадающее с именем класса. Конструкторы должны иметь различную сигнатуру (отличаться числом и/или типами аргументов).
Как мы видели при обсуждении перегрузки, сигнатура не является подходящим критерием распознавания. Например: конструкторы make_cartesian и make_polar имеют одинаковую сигнатуру, так что придется вводить искусственный аргумент в один из конструкторов, чтобы стало возможным отличить вызов нужного конструктора.
