X, y : Integer; // Объявляем
Color : TColor; // поля даннях
public // Доступно всем
Constructor Create(x0, y0 : Integer; Color0 : TColor); // Объявляем конструктор Создать
Procedure Show; // Объявляем метод Показать
end;
4. Пример реализации класса TPoint
implementation// В разделе реализации модуля
constructor TPoint.Create(x0, y0 :Integer; Color0 : TColor); // Реализуем конструктор Создать
Begin
x := x0; // Начальная инициализация
y := y0; // полей данных
Color := Color0;
end;
procedure TPoint.Show; // Реализуем метод Показать
Begin
Form1.Canvas.Pixels[x, y] := Color;
end;
5. Пример создания экземпляра класса TPoint
Для создания объекта TPoint (точка) необходимо объявить переменную данного класса:
Var
Point1 : TPoint;// Переменная Point1 является экземпляром класса TPoint
После этого для данной переменной необходимо вызвать конструктор класса, который осуществляет инициализацию объекта:
// в обработчике события OnCreate
Point1 := TPoint.Create(100, 100, clRed); // Создание объекта Point1
Далее можно вызывать методы и изменять свойства объекта Point1:
// в обработчике события OnPaint
Point1.Show; // Отобразить точку
Point1.Color := clGreen; // Изменить цвет точки
После работы с объектом необходимо освободить занимаемую им память:
// в обработчике события OnDestroy
Point1.Free; // Уничтожение объекта Point1
Примечание. Изменять поля данных нужно только используя методы класса. Вызов Point1.Show без предварительного вызова конструктора приведет к неудачному завершению программы.
6. Пример создания массива экземпляров класса TPoint
Создание массивов объектов требует обязательной инициализации каждого экземпляра класса.
Var
Points : Array [1..5] of TPoint; // Объявление переменной Points как массива объектов типа TPoints
i : Integer;
Begin
for i := 1 to 5 do Points[i] := TPoint.Create(100+20*i, 150, clGreen); // Создание массива объектов
// типа TPoints
end;
…
for i := 1 to 5 do Points[i].Free; // Уничтожение массива объектов типа TPoints
7. Иерархия классов Delphi. Коструктор Create и деструктор Destroy класса TObject
В Delphi принимается, что все классы порождены от базового класса TObject. Этот класс не имеет полей, однако включает методы самого общего назначения, например выделения и освобождения памяти под объект.
Программист не может создать класс, который бы не был производным от TObject.
Таким образом, следующие записи идентичны:
TPoint = class
TPoint = class(TObject)
В TObjectобъявлены базовые конструктор Create и деструктор Destroy класса.
При определении конструктора дочернего класса необходимо вызвать конструктор родительского класса. Вызов любого метода родительского класса осуществляется указанием ключевого слова inherited.
constructor TPoint.Create(x0, y0 :Integer; Color0 : TColor); // Реализуем конструктор Создать
Begin
inherited Create; // Вызов конструктора Create класса TObject
x := x0; // Начальная инициализация
y := y0; // полей данных
Color := Color0;
end;
После завершения работы с объектом необходимо вызвать деструктор Destroy:
Point1.Destroy; // Вызов деструктора Destroy
Вызов деструктора возможен только если объект был ранее создан при помощи конструктора класса. Поэтому более корректно использовать метод Free класса TObject, который сперва проверяет, был ли создан экземпляр класса, и только после этого вызывает деструктор:
Point1.Free; // Вызов метода Free класса TObject
8. Свойства конструкторов и деструкторов
Конструкторы и деструкторы представляют собой специальные виды методов, которые служат для создания и уничтожения объектов и объявляются при помощи ключевых слов constructor и destructor.
Свойства конструкторов:
31. Конструкторы используются для выделения памяти и инициализации вновь созданных объектов. Обычно инициализация основывается на значениях, передаваемых конструктору в качестве параметров.
32. Конструктор распределяет объект в динамической памяти и помещает адрес этой памяти в переменную Self, которая неявно объявляется в объекте.
33. Обращение к полям объекта, а также вызов методов, которые оперируют с этими полями, возможно только после вызова конструктора класса.
34. Конструктор дочернего класса должен вызывать конструктор непосредственного родителя для инициализации наследуемых полей. После этого конструктор инициализирует собственные поля данных.
Свойства деструкторов:
35. Деструкторы используются для удаления объектов после их использования (освобождения памяти и завершающих действий).
36. Деструктор дочернего типа обычно сначала удаляет собственные поля, а затем вызывает деструктор непосредственного родителя для удаления унаследованных полей данных.
9. Вызов методов
Синтаксис:
<Имя объекта>.<Имя метода>;
Например:
Point1.Show;
Point1.Hide;
10. Вызов методов класса
Существует ряд методов, которые можно вызывать, используя для вызова не имя объекта, а имя класса. Эти методы называются методами класса. Их можно вызывать до создания экземпляров класса, однако из них нельзя обращаться к полям данных класса.
Для вызова метода класса используется синтаксис:
<Имя класса >.<Имя метода>;
Пример:
Point1 := TPoint.Create(100, 100, clRed);
11. Указатель на текущий экземпляр класса Self
В языке Object Pascal введена переменная Self которая всегда указывает на текущий объект – экземпляр класса.
При вызове любого метода в качестве неявного параметра автоматически передается переменная Self, указывающая на экземпляр класса, для которого был вызван метод. Это необходимо делать, т.к. для множества экземпляров объектов существует лишь один экземпляр методов. Параметр Self всегда передается последним.
12. Пример объявления дочернего класса TCircle
Построим на основе базового класса TPoint (точка) дочерний класс TCircle (окружность).
Type
TPoint = class (TObject)
Private
x, y : Integer; // ОбПоля данных
Color : TColor;
Public
// Объявление конструктора Create
constructor Create(x0, y0 : Integer; Color0 : TColor);
// Переопределение виртуального деструктора Destroy класса TObject
destructor Destroy; override;
// Виртуальные методы работы с Точкой
procedure Show; virtual; // Метод для отображения объекта
procedure Hide; virtual; // Метод для скрытия объекта
procedure Move(dx, dy:Integer); // Метод для перемещения объекта
end;
TCircle = class(TPoint)
Private
Radius : Integer; // Дополнительное поле – радиус окружности
Public
// Переопределение конструктора родительского класса
constructor Create(x0, y0, Radius0 : Integer; Color0 : TColor);
// Переопределение виртуального деструктора Destroy класса TObject
destructor Destroy; override;
// Переопределение методов работы с Окружностью
procedure Show; override;
procedure Hide; override;
procedure Move(dx, dy:Integer); override;
end;
13. Пример реализации дочернего класса TCircle
constructor TCircle.Create(x0, y0, Radius0 : Integer; Color0 : TColor);
begin
inherited Create(x0, y0, Color0); // Вызов конструктора базового класса
Radius := Radius0; // Инициализация дополнительного поля
end;
procedureTCircle.Show;
Begin
Form1.Canvas.Pen.Color := Color;
Form1.Canvas.Ellipse(x-Radius, y-Radius, x+Radius, y+Radius);
end;
procedureTCircle.Hide;
Begin
Form1.Canvas.Pen.Color:=Form1.Color; // Установить цвет Пера как цвет формы
Form1.Canvas.Ellipse(x-Radius,y-Radius,x+Radius,y+Radius);
end;
procedureTCircle.Move(dx,dy:integer);
Begin
Circle.Hide; // Стереть окружность
x:=x+dx; // Изменить координаты
y:=y+dy;
Circle.Show; // Показать окружность
end;
destructorTCircle.Destroy;
Begin
Circle.Hide; // Стереть окружность
inherited Destroy; // Вызвать базовый деструктор
end;
14. Совместимость переменных родительских и дочерних классов
Переменная базового типа может указывать на любой производный от него тип. Например, переменная типа TPoint может указывать на любой экземпляр дочернего по отношению к TPoint типа.
TPoint = class(TObject);
TCircle = class(TPoint);
Var
Point: TPoint;
Circle: TCircle;
…
Point := Circle; // Point будет указывать на Circle
15. Статические и виртуальные методы
Методы классов делятся на статические (по умолчанию), виртуальные (директива virtual), динамические (директива dynamic) и абстрактные (директива abstract).
По умолчанию все методы статические. Если в классе-наследнике переопределить такой метод (ввести новый метод с таким же именем), то для объектов этого класса новый метод отменит родительский. Если обращаться к объекту этого класса, то вызываться буде уже новый метод. Но если обратиться к объекту как к объекту родительского класса, то вызываться будет уже метод родителя. Для статических методов вызов конкретного метода определяется на этапе компиляции через механизм статического связывания.
Виртуальные методы не связаны с другими методами с тем же именем в классах-наследниках. Если в классах-наследниках эти методы перегружены, то при обращении к такому методу во время выполнения будет вызываться тот из методов с одинаковыми именами, который соответствует классу объекта, указанному при вызове. Т.е. для виртуальных методов выбор конкретного метода определяется во время выполнения программы в зависимости от типа объекта, для которого вызван метод (механизм позднего (динамического) связывание). Метод, объявленный как виртуальный, остаётся виртуальным во всех классах-наследниках.
16. Переопределение методов
Дочерний класс может переопределять любой из методов, который он наследует от своих родителей.
Для переопределения родительского метода необходимо объявить в потомке метод с тем же именем. Этот метод будет действовать в иерархии потомков до тех пор, пока снова не будет переопределен.
При переопределении статического метода можно изменять тип параметров и тип возвращаемого значения метода.
Переопределение виртуального метода должно включать директиву override. Переопределение виртуального метода должно в точности сохранять порядок, типы и имена параметров, а также тип возвращаемого значения метода.
17. Пример вызова виртуальных методов
Var
Point: TPoint;
Circle: TCircle;
…
Point := TPoint.Create;
Circle := TCircle.Create;
Point.Show; // Рисование точки
Point.Move; // Перемещение точки
Point := Circle; // Point будет указывать на Circle
Point.Show; // Рисование окружности
Point.Move; // Перемещение окружности
Правила совместимости типов позволяют Point указывать на ТPoint, TCircle и на любых других потомков TPoint. В зависимости от фактического типа во время выполнения программы будет вызвана либо TPoint.Show, либо TCircle.Show.
Если бы Show являлся статическим методом, то не имело значения, на что указывает Point, и всегда вызывался метод TPoint.Show.
Метод Move объявлен в классе TPoint и является статическим, однако содержит вызовы виртуальных методов Hide и Show, поэтому может перемещать и точку, и окружность.
Такой подход позволяет оперировать одинаковыми методами с разными по типу объектами, причем этот тип изменяется в ходе выполнения программы.