Основы объектно-ориентированного программирования
Шрифт:
Для чего необходимо явное создание объектов?
Объекты создаются явным образом. Объявление сущности
не влечет за собой создание объекта во время выполнения, это происходит, когда некий элемент системы выполнит операцию
Это может показаться удивительным. Разве объявления b недостаточно для создания объекта? Что хорошего в объявлении, если объект не создается?
Достаточно минуты размышления для понимания того, что разделение объявления и создания объекта является единственно разумным решением.
Первый аргумент - reductio ad absurdum (доведение до абсурда). Предположим, что начата обработка объявления и немедленно создается соответствующий объект. Но это экземпляр класса BOOK3, имеющий атрибут author ссылочного типа WRITER, значит поле author– ссылка, для которой опять нужно создавать объект. Этот объект вновь содержит ссылочные поля, требуется опять делать то же самое и начинается длинный путь рекурсивного создания объектов.
Этот аргумент еще более убедителен для таких классов как PERSON1, содержащих ссылки на себя:
Появление каждого экземпляра PERSON1 повлечет за собой создание двух других таких объектов (соответствующих loved_one и landlord ) и начнется бесконечный цикл. Такие прямые или косвенные циклические ссылки не экзотика - они часто встречаются и необходимы.
Другой аргумент следует из обсуждения роли объектной технологии как мощного метода моделирования. Если для каждого ссылочного поля будет создаваться новый объект, то не было бы возможности выделить пустые ссылки и множественные ссылки на один и тот же объект. И то, и другое необходимо для реалистичного моделирования систем:
[x]. В некоторых случаях требуется, чтобы ссылка не была связана ни с каким объектом. Примером может служить пустая ссылка author для обозначения неизвестного автора.
[x]. В других случаях, в соответствии с моделью две ссылки должны быть присоединены к одному объекту. (См. рис.8.7 ) В примере с циклическими ссылками присутствовали поля loved_one двух персон PERSON1, присоединенные к одному и тому же объекту. Не имело бы смысла создание своего объекта для каждого из этих полей. Все, что требуется, - это операция присваивания (рассмотрена далее в этой лекции) для присоединения ссылки к уже существующему объекту. В еще большей степени это соображение применимо для ссылки на себя (поле landlord верхнего объекта в том же примере).
Механизм управления объектами никогда не присоединяет ссылку неявно. Он создает объекты через инструкции создания (или операции клонирования, тоже явные), инициализируя их ссылочные поля пустыми ссылками. Эти поля, в свою очередь, могут стать присоединенными к объектам, только в результате явных операций над этими полями.
| В дискуссии о наследовании будет показано, что инструкция создания может использовать синтаксис create {T}x для создания объекта, чей тип T является наследником типа объявленного для x. (Полиморфное создание, см.лекцию 14) |
Процедуры создания
Все до сих пор рассмотренные инструкции создания основывались на инициализации по умолчанию. В некоторых случаях инициализация, определенная в языке, может нас не устраивать - хотелось бы обеспечить создаваемый объект специфической информацией. В этом предназначение процедур создания.
Перекрытие инициализации по умолчанию
Для использования инициализации, отличной от предопределенной умолчанием, необходимо класс снабдить одной или несколькими процедурами создания. Такие процедуры должны быть перечислены в предложении, начинающимся ключевым словом creation в начале класса перед первым предложением feature. Схема такова:
| Совет, отражающий стиль: в случае класса с единственной процедурой создания - для нее рекомендуется имя make. Для классов с двумя и более процедурами создания желателен префикс make_, за которым следует квалификатор, как в следующем примере POINT. (См. "Правильный выбор имен", лекция 8 курса "Основы объектно-ориентированного проектирования") |
Соответствующая инструкция создания в этих случаях имеет другую форму:
где p одна из процедур создания перечисленных в разделе creation, и в круглых скобках (...) перечисляются фактические аргументы p. Результатом является создание объекта с использованием значений по умолчанию, как и ранее, а затем вызов p с заданными аргументами. Такая инструкция является комбинацией инструкции создания и вызова процедуры и называется порождающим вызовом (creation call). (Оригинальная версия класса POINT приведена в лекции 7)
В качестве примера добавим две процедуры создания в класс POINT, что позволит клиентам при создании новой точки указывать ее начальные координаты - декартовы или полярные. Введем процедуры создания: make_cartesian и make_polar. Вот схема: