Основы объектно-ориентированного программирования
Шрифт:
[x]. (T4) Если x– локальная сущность r, то к моменту вызова предыдущие инструкции вычислят значение x, присоединенное к определенному объекту, который и является объектом t.
Проблема в том, что все четыре ответа опять относительны и могут помочь только в том случае, если известно, чем является текущий экземпляр OBJ. Очевидно, что OBJ это цель текущего вызова! Ситуация как в песенке о том, как у попа была собака (в оригинале: котенок съел козленка, котенка укусил щенок, щенка ударила палка ...) - бесконечная цепь.
Для приведения относительных ответов к абсолютным необходимо выяснить, что происходит тогда, когда все только начинается - в момент Большого Взрыва. Итак, определение:
Определение: выполнение системы
Выполнение ОО-программной системы состоит из следующих двух шагов:
[x]. Создание определенного объекта, называемого корневым объектом выполнения.
[x]. Применение определенной процедуры, называемой процедурой создания, к данному объекту.
В момент Большого Взрыва создается объект и начинается выполнение процедуры создания. Корневой объект является экземпляром корневого класса системы, а процедура создания - одной из процедур этого класса. Выполнение системы в целом сводится к успешному развертыванию отдельных частей (прямо или косвенно зажженных от начальной искры) в гигантский комплексный фейерверк.
Зная, где все началось, несложно проследить судьбу Current в процессе этой цепной реакции. Первым текущим объектом, созданным в момент Большого Взрыва, является корневой объект. Рассмотрим далее некоторый этап выполнения системы. Пусть r– последняя вызванная подпрограмма, а текущим на момент вызова r был объект OBJ. Тогда во время выполнения r объект Current определяется следующим образом:
[x]. (C1) Если в r выполняется инструкция, не являющаяся вызовом подпрограммы (например, присваивание), то текущим остается прежний объект.
[x]. (C2) Неквалифицированный вызов также оставляет тот же объект текущим.
[x]. (C3) Запуск квалифицированного вызова x.f ... делает текущим объект, присоединенный к x. Зная объект OBJ, можно идентифицировать x, используя сформулированные ранее правила T1-T4. После завершения вызова роль текущего возвращается к объекту OBJ.
В случаях C2 и C3 вызов может в свою очередь содержать последующие квалифицированные или неквалифицированные вызовы, и данные правила нужно применять рекурсивно.
Итак, нет ничего загадочного и запутанного в определении цели любого вызова, несмотря на всю относительность и рекурсивность правил. Что действительно является удивительным, так это мощь компьютеров, которую мы используем, выступая в роли учеников чародея. Мы создаем относительно небольшой текст заклинания - ПО, и затем выполняем его, в результате чего создаются объекты и выполняются вычисления, и число этих объектов и вычислений столь велико, что кажется почти бесконечным по меркам человеческого сознания.
Системы
Эта лекция акцентирует внимание на классах - элементах конструкции ОО-ПО. Для получения исполняемого кода классы необходимо скомпоновать в систему.
Определение системы вытекает из предшествующего обсуждения. Для построения системы необходимы три вещи:
[x]. Создать совокупность классов CS, называемую множеством классов (class set) системы.
[x]. Указать класс из CS, являющийся корневым (root class).
[x]. Указать в корневом классе процедуру, играющую роль корневой процедуры создания (root creation procedure) .
Для получения системы эти элементы должны удовлетворять критерию целостности. Каждый класс, прямо или косвенно необходимый корневому, должен быть частью множества CS. Это условие замыкания системы (system closure) .
Понятие необходимости следует уточнить, как это обычно делается при построении замыкания:
[x]. Класс D непосредственно необходим классу C , если текст C ссылается на D. Здесь можно выделить два варианта: C может быть либо клиентом D, либо потомком D.
[x]. Класс E необходим классу C, либо, когда C совпадает с E, либо существует класс D непосредственно необходимый классу С, и классу D необходим (возможно, рекурсивно) класс E. Другими словами, существует цепочка классов, связанных отношением непосредственной необходимости, и началом этой цепочки является класс C, а концом - класс E.
Теперь можно дать определение замкнутой системы.
Определение: замкнутая система
Система является замкнутой, если и только если множество ее классов содержит все классы, необходимые корневому классу.
Специализированная программа, например компилятор, может обработать все классы замкнутой системы, начиная с корневого. Рекурсивное обращение к необходимым классам будет происходить по мере того, как встретится упоминание о них. В результате будет сформирован исполняемый код, соответствующий системе в целом.
Этот процесс называется компоновкой или сборкой (assembly) системы и является завершающим этапом разработки.
Программа main отсутствует
Неоднократно подчеркивалось, что системы, разработанные с помощью ОО-подхода, не используют понятия основной программы. Не впускаем ли мы основную программу с черного хода, вводя определение корневого класса и корневой процедуры?
Не совсем. В традиционном понятии основной программы объединены две не связанные концепции:
[x]. Место, с которого начинается выполнение.
[x]. Вершина или фундаментальный компонент архитектуры системы.
Первое условие, безусловно, необходимо. Выполнение любой системы должно начинаться с вполне определенной позиции. В ОО-системах эта позиция определяется корневым классом и корневой процедурой. В случае параллельных, а не последовательных вычислений можно определить несколько начальных точек - по одной для каждой независимой нити или потока (Thread) вычислений.