Виртуальные и динамические методы
Классы
Классами в системе программирования Delphi называются специальные типы,
которые содержат составляющие класса: поля, методы и свойства. Составляющие класса
часто называют членами класса. Класс предназначен для создания конкретных экземпляров реализации, которые называются объектами.
Описание класса
Формат описания класса.
Type
<Имя класса> = Class
// члены класса
Поля
Свойства
Методы
End;
В основе класса лежат три фундаментальных принципа инкапсуляция, наследование и полиморфизм.
Инкапсуляция
Объединение в классе в одно целоеего членов называется инкапсуляцией.Инкапсуляция позволяет разграничить доступ к различным полям и свойствам класса. Некоторые поля и методы можно сделать свободно доступными в любом месте программы, другие поля и методы только внутри класса.
Наследование
Любой класс может быть порожден от другого класса. Тогда при объявлении такого класса после ключевого слова Class в круглых скобках указывается имя класса родителя.
TChildClass = Class(TParentClass)
End;
Порожденый класс автоматически наследует поля, методы и свойства своего родителя и может добавлять к ним новые. Таким образом, принцип наследования обеспечивает поэтапное создание сложных классов и разработку собственных библиотек классов.
Все классы Delphi порождены от единственного родителя – класса TObject.
TaClass=Class(TObject);
Или
TaClass=Class;
Оба объявления равносильны.
Класс TObject. не имеет полей и свойств, но включает в себя множество методов самого общего назначения, обеспечивающие весь жизненный цикл любых объектов – от их создания до уничтожения.
Принцип наследования приводит к созданию ветвящегося дерева классов, постепенно разрастающегося при перемещении от класса TObject к его потомкам. Каждый потомок дополняет возможности своего родителя новыми возможностями и передает их своим потомкам.
Дочерний класс не может удалить какую-либо сущность родительского класса.
Полиморфизм
Полиморфизм- это свойство классов решать схожие по смыслу проблемы разными способами. Поведенческие свойства класса определяются набором входящих в него методов(процедуры и функции). Изменяя алгоритм того или другого метода в потомках класса, можно придавать этим потомкам отсутствующие у родителя специфические свойства. Для изменения метода необходимо перекрыть его в потомке, то есть объявить в потомке одноименный метод и реализовать в нем отличные от родителя действия. В результате в объекте-родителе и объекте-потомке будут действовать два одноименных метода, имеющих разную алгоритмическую основу, и, следовательно, придающие объектам разные свойства. Это и называется полиморфизмом объектов.
Составляющие класса
Поля.Полями называются инкапсулированные в классе данные. Поля могут быть любого типа, в том числе и классами. Например:
Type
TMyClass= class
aIntField: Integer;
aStrField: String;
aObjField: TObject;
…
End;
Каждый объект получает уникальный набор полей, но общий для всех объектов данного класса набор методов и свойств. Фундаментальный принцип инкапсуляции требует обращаться к полям только с помощью методов и свойств класса. Но в Delphi разрешается обращаться к полям напрямую. Доступ к полям возможен с помощью составных имен(как при доступе к полям записи):
Type
TMyClass= class
FIntField: Integer;
FStrField: String;
…
End;
В разделе описания переменных объявляется переменная этого класса, которая называется экземпляром класса или объектом.
Var
aObject: TMyClass;
Экземпляр класса является динамической переменной – указателем, содержащим адрес объекта.
Begin
…
//Составные имена – это имя переменной (точка)имя поля
aObject.FIntField:=0;
aObject.FStrField:=’Строка символов’;
…
End.
Класс потомок получает все поля своих предков и может дополнять их своими, но не может их переопределять или удалять. Таким образом, чем ниже в дереве иерархии располагается класс, тем больше данных получает в свое распоряжение его объекты.
Методы
Инкапсулированные в классе процедуры и функции называются методами.
Они объявляются так же, как и обычные подпрограммы. Доступ к методам осуществляется с помощью составных имен:
Type
TMyClass= class
Function MyFunc(aPar:Integer):Integer;
Procedure MyProc;
End;
Var
aObject: TMyClass;
Begin
…
// Вызов метода через составное имя –это имя переменной(точка)имя метода
aObject.MyProc;
…
End.
Типы методов
В Delphi поддерживаются статические, виртуальные, динамические, перегружаемые и абстрактные методы.
Статические методы
Все методы по умолчанию считаются статическими
Type
TParentClass= Class
Procedure DoWork;
End;
TChildClass= Class(TParentClass)
Procedure DoWork;
End;
Var
Object_a: TParentClass;
Object_b: TGhildClass;
Потомки обоих классов могут выполнять сходную по названию процедуру DoWork, но
будут делать ее по-разному. Такое замещение методов называется статическим, так как реализуется компилятором.
Виртуальные и динамические методы
В Delphi чаще используется динамическое замещение методов на этапе прогона программы. Для реализации этого метода, замещаемый в родительском классе, должен объявляться как динамический (с директивой Dynamic) или виртуальный ( с директивой Virtual). В классе потомке замещаемый метод объявляется с директивой Override(перекрыть).
Перекрытие методов
Методы класса могут перекрываться в потомках.
Например, пусть родительский класс с помощью методов Show и Hide показывает изображение или прячет его на экране. Изображение создается методом Draw.
Type
TVisualObject=Class( TWinControl);
Procedure Show;
Procedure Hide;
Procedure draw(IsShow:Boolean); Virtual;//замещаемый
End;
TVisualChildObject=Class(TVisualOdject);
Prvirtual;ocedure draw(IsShow:Boolean); Override;//замещающий
End;
Реализация методов Show и Hide очень проста .
Procedure TVisualObject.Show;
Begin
Draw(True);
End;
Procedure TVisualObject.Hide;
Begin
Draw(False);
End;
Методы Draw у родителя и потомка имеют разную реализацию и создают разные изображения. В результате родительские методы Show и Hide будут прятать или показывать те или иные изображения в зависимости от конкретной реализации метода
Draw у любого из своих потомков. Динамическое связывание в полной мере реализует
полиморфизм классов.
Абстрактные методы
Динамические перекрываемые методы часто могут ничего не делать. Такие методы называются абстрактными,они обязаны перекрываться в потомках. Можно запретить вызов абстрактного метода, объявив его с директивой Abstract. Например
Type
TVisualObject=Class( TWinControl);
procedure draw(IsShow:Boolean);virtual;abstract;
End;
TVisualChildObject=Class(TVisualOdject);
Procedure draw(IsShow:Boolean); Override;
End;
Var
aVisualObject: TVisualObject;
aVisualChildObject: TVisualChildObject;
begin
aVisualObject.Show; //Ошибка! Обращение к абстрактному методу
aVisualChildObject.Show; // Верное Обращение. Метод Draw у класса TVisualChildObject
// перекрыт
end;