Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
[ Монахов ] Объектно-ориентированное программирование.doc
Скачиваний:
94
Добавлен:
16.08.2013
Размер:
490.5 Кб
Скачать

4.10. Создание и уничтожение объектов. Конструкторы и деструкторы.

В Object Pascal объекты могут быть только динамическими! Любая переменная объектного типа — это указатель, но доступ к объекту идет без 'шляпки', а создание нового объекта осуществляется не оператором New, а с помощью вызова конструктора — функции, возвращающей указатель на создаваемый объект. Соответственно, уничтожение объекта производится не с помощью Dispose, а вызовом деструктора. Поэтому обычно в Delphi конструктор называют Create ("создать"), а деструктор — Destroy ("уничтожить, разрушить"):

aMyObject:=tMyObject.Create; {создали объект aMyObject типа tMyObject

и запомнили указатель на него}

...

aMyObject.Destroy; {уничтожили объект}

Заметим, что конструктор — это метод класса, и он работает без экземпляра объекта (экземпляра еще нет, но метод создает его). В Delphi конструкторы могут быть виртуальными, и их может быть несколько. Сразу при входе в конструктор желательно проинициализировать прародителя:

constructor tMyObject.Create;

begin

inherited Create;

...

end;

В данном примере инициализация прародителя осуществляется с помощью специального ключевого слова inherited, которое появилось еще в TurboPascal 7.0. Оно означает, что следующий за ним вызов относится к непосредственному прародителю данного объекта. Многократные вызовы типа inherited inherited запрещены, чтобы не вызвать неправильной инициализации объекта.

Если наш класс описан как

tMyObject=class(tObj1)

...

end;

то вызов inherited Create абсолютно логичен вызову tObj1.Create.

4.11. Наследование. Статические, виртуальные, динамические и абстрактные методы.

Все классы Delphi — потомки класса tObject. Если нет указания, какой класс является прародителем, значит, это tObject. Определение

tMyObject=class

...

end;

полностью равносильно

tMyObject=class(tObject)

...

end;

Вызываемые методы делятся на статические (static), виртуальные (virtual) и динамические (dynamic). Есть еще методы, которые не содержат никаких действий (нет реализации), никогда не вызываются и нужны только для наследования — абстрактные (abstract). Абстрактными могут быть только виртуальные или динамические методы, причем у них имеется только заголовок (в описании класса) и отсутствует реализация.

Переопределение методов в потомках называется перекрытием этих методов, а сами переопределенные методы прародителя — перекрытыми (override) потомком.

Перекрытие статических методов происходит так же, как в Turbo Pascal. Для виртуальных методов синтаксис изменен: в первом из прародителей, где определяется виртуальный метод, ставится ключевое слово virtual, а в потомках для перекрывающих методов — override.

Для виртуальных методов в классе постоянно хранятся адреса всех имеющихся в данном классе виртуальных методов независимо от того, унаследованы они или перекрыты. Виртуальные методы вызываются быстро, но таблица виртуальных методов (VMT) может занимать много места, если имеется длинная цепочка наследования с большим количеством методов в каждом классе. Динамические методы являются более экономичными по памяти и более медленным аналогам виртуальных. Каждому динамическому методу системой присваивается уникальный индекс. В таблице динамических методов (DMT) класса хранятся индексы и адреса только тех динамических методов, которые описаны в данном классе. Если при вызове нужный метод в таблице не найден, просматривается таблица прародителя, и т.д. вплоть до tObject. В остальном разницы между виртуальными и динамическими методами нет. Стоит отметить, что Delphi предоставляет существенно больший набор средств программирования, чем, например, Java, где ни статических, ни виртуальных методов нет, а только динамические.

Вызов не перекрытого абстрактного метода (т.е. помеченного директивой abstract) дает диагностику ошибки. Абстрактные методы используются на начальном уровне описания иерархии, а такая диагностика помогает при отладке программы находить потомки, в которых программист забыл перекрыть необходимые методы.

Пример использования виртуальных и абстрактных методов:

type

tField=

class function GetData:string;virtual;abstract; {нужна для работы

ShowData1}

tStringField=

class(tField)

fData:string;

function GetData:string;override;{перекрыли абстрактный метод}

end;

tIntegerField=

class(Field)

fData:Integer;

function GetData:string;override; {то же}

end;

...

{-реализация перекрывающих методов-}

function tStringField.GetData:string;

begin

GetData:=fData; {присваивание строкового поля}

end;

function tIntegerField.GetData:string;

begin

GetData:=IntToStr(fData); {преобразование из целого в строку}

end;

...

{-процедура, которая работает для разных типов полей-}

procedure ShowData(aField:tField);

begin

Form1.Label1.Caption:=aField.GetData;{вызов метода, который для

класса tField абстрактный}

end;

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

Особенность нового синтаксиса для объектов — то, что динамически созданный объект как параметр можно передавать как по значению (см. ShowData), так и по имени (см. далее ShowData1):

procedure ShowData1(var aField:tField);

begin

...

end.

При этом в случае передачи по значению котируется только указатель на объект, но не его тело. В Object Pascal, в отличие от C++, нет понятия "конструктора копии", и при необходимости скопировать тело объекта надо просто задать метод объекта, который занимается его копированием.

Соседние файлы в предмете Информатика