Классы на Object Pascal
Описание классов на Object Pascal
Тип данных — статический описание совокупности динамических объектов, объединенных определенными операциями. В ООП каждый тип базируется на определенном классе. Класс — это тип данных с частичной или полной реализацией операций.
view plaincopy to clipboardprint?
- type <имя класса> = class (<имя родительского класса>)
- private
- {Поля, методы}
- protected
- {Поля, методы, свойства}
- public
- {Поля, методы, свойства}
- published
- {Поля, методы, свойства}
- end;
type <имя класса> = class (<имя родительского класса>)
private
{Поля, методы}
protected
{Поля, методы, свойства}
public
{Поля, методы, свойства}
published
{Поля, методы, свойства}
end;
Имя класса — любой идентификатор; как правило, начинается с большой буквы Т. Имя сверхкласса может не указываться, тогда считается, что класс является непосредственным потомком класса TObject.В ObjectPascal класс TObject является базовым классом для всех объектов.
В описании класса определяют поля и методы.
Поля — это определенные характеристики объектов класса (описывают как переменные).
Методы — это операции над объектами класса (описывают как процедуры и функции).
Следующие директивы управляют правами доступа к элементам класса.
Private (личный, закрытый) содержит поля и методы, которые используются только объектами этого класса.
Protected (защищенный) содержит поля и методы, доступные также для всех потомков этого класса.
Public (открытый) — поля и методы, а также свойства, доступные для внешнего использования, в том числе по объектам других классов.
Published (для публикации) содержит поля, методы, которые являются открытыми, а также свойства которые будут доступны при проектировании в инспекторе объектов Delphi (для просмотра и изменения).
Если директивы не указаны, то по умолчанию считается, что установлены директиву Published.
Пример класса: TPoint — точки на плоскости
view plaincopy to clipboardprint?
- type
- TPoint = class
- X, Y: Real; // координаты в декартовой системе
- function Ro: Real; // координаты
- function Fi: Real; // в полярной системе
- function Distance (p: TPoint): Real;
- // расстояния между двумя точками;
- procedure Translate (dx, dy: Real)
- // перемещения;
- procedure Rotate (p: TPoint; f: Real)
- // вращения точки на определенный угол вокруг другой точки (центра вращения)
- procedure Scale (k: Real)
- // масштабирование
- end;
type
TPoint = class
X, Y: Real; // координаты в декартовой системе
function Ro: Real; // координаты
function Fi: Real; // в полярной системе
function Distance (p: TPoint): Real;
// расстояния между двумя точками;
procedure Translate (dx, dy: Real)
// перемещения;
procedure Rotate (p: TPoint; f: Real)
// вращения точки на определенный угол вокруг другой точки (центра вращения)
procedure Scale (k: Real)
// масштабирование
end;
В этом описании:
X, Y — поля класса;
Ro, Fi, Distance, Translate, Rotate, Scale — методы класса.
Возможно описание, где X и Y будут методами, а Ro и Fi — полями:
// …
Ro, Fi: Real; // координаты в полярной системе
function X: Real; // координаты
function Y: Real; // в декартовой системе
В Object Pascal описание класса вместе с полями и прототипами методов включается в открытую часть программного модуля, называется интерфейсом (англ. Interface).Реализация методов включается в закрытой части модуля называется реализацией (англ. Implementation).
view plaincopy to clipboardprint?
- implementation
- function TPoint.Ro: Real;
- begin
- Ro = sqrt (sqr (X) + sqr (Y))
- // или
- // Result: = sqrt (sqr (X) + sqr (Y))
- end;
- function TPoint.Fi: Real; // в полярной системе
- begin
- Fi = ArcTan (Y / X);
- end;
- function TPoint.Distance (p: TPoint): Real;
- begin
- Distance = sqrt (sqr (Xp.X) + sqr (Yp.Y))
- end;
- procedure TPoint.Translate (dx, dy: Real)
- begin
- X = X + dx;
- Y = Y + dy;
- end;
- procedure TPoint.Rotate (p: TPoint; f: Real)
- var x1, y1: real;
- begin
- x1 = (Xp.X) * cos (f) — (Yp.Y) * sin (f) + p.X;
- y1 = (Xp.X) * sin (f) + (Yp.Y) * cos (f) + p.Y;
- X = x1; Y = y1;
- end;
- procedure TPoint.Scale (k: Real)
- begin
- X = k * X;
- Y = k * Y;
- end;
implementation
function TPoint.Ro: Real;
begin
Ro = sqrt (sqr (X) + sqr (Y))
// или
// Result: = sqrt (sqr (X) + sqr (Y))
end;
function TPoint.Fi: Real; // в полярной системе
begin
Fi = ArcTan (Y / X);
end;
function TPoint.Distance (p: TPoint): Real;
begin
Distance = sqrt (sqr (Xp.X) + sqr (Yp.Y))
end;
procedure TPoint.Translat e (dx, dy: Real)
begin
X = X + dx;
Y = Y + dy;
end;
procedure TPoint.Rotate (p: TPoint; f: Real)
var x1, y1: real;
begin
x1 = (Xp.X) * cos (f) — (Yp.Y) * sin (f) + p.X;
y1 = (Xp.X) * sin (f) + (Yp.Y) * cos (f) + p.Y;
X = x1; Y = y1;
end;
procedure TPoint.Scale (k: Real)
begin
X = k * X;
Y = k * Y;
end;
Описание объектов на Object Pascal. создание объектов
Объект — это экземпляр определенного класса.Объект описывается как переменная, тип переменной — это класс объекта.
пример
var P1, P2: TPoint;
Название объекта является указателем на этот объект. При описании переменных-объектов в памяти выделяется место только под указатель (4-байтный адрес). Начальное значение этого адреса равен nil (неопределенный указатель).
Таким образом, объекты в Object Pascal являются динамическими переменными, то есть создаются во время работы программы.Но, при работе с объектами, в отличие от указателей, розадресация указателя (^), процедуры New и Dispose не используются.
Для создания объектов используют специальный метод — конструктор, который обозначается ключевым словом constructor.Как правило, этот метод называется Create.
пример:
view plaincopy to clipboardprint?
- type TPoint = class
- // …
- constructor Create;
- // …
- end;
- var P1, P2: TPoint;
- constructor TPoint.Create;
- Begin
- X = 0;
- Y = 0;
- End;
- begin
- P1 = TPoint.Create;
- P2 = TPoint.Create;
- // …
- end;
type TPoint = class
// …
constructor Create;
// …
end;
var P1, P2: TPoint;
constructor TPoint.Create;
Begin
X = 0;
Y = 0;
End;
begin
P1 = TPoint.Create;
P2 = TPoint.Create;
// …
end;
В данной реализации конструктор вызывается без параметров.
Можно реализовать конструктор в виде:
constructor TPoint.Create (a, b: Real)
begin
X = a;
Y = b;
end;
Тогда вызвать конструктор можно, например
P1 = TPoint.Create (1, 2);
Внутри методов можно использовать переменную Self, которая обозначает объект, для которого вызывается данный метод.В частности, для решения коллизий (противоречий) между названиями полей и локальных переменных и параметров методов можно указать эту переменную перед названиями полей, например
Self.X = X;
Self.Y = Y;
Если конструктор реализовано, но в нем нет присвоении начальных значений полям объекта, то происходит инициализация по умолчанию. Числовые переменные инициализируются значениями 0, символьные — нуль-символом (# 0), логические переменные — значением false, указатели — значением nil.
Таким образом, в отличие от указателей процедура new для создания объектов не используется, если существует конструктор.Но переменная, которая обозначает объект в операциях используется подобно указателей.
Инициализация объектов, обращения к полям и методам. свойства
При написании программы доступ к полям (для чтения) не отличается от доступа к методу без аргументов (функции) — принцип однородного доступа. Например:
X1 = P1.X; // обращение к полю;
Ro1 = P1.Ro; // обращение к методу.
Объект, для которого вызывается метод, называемый также получателем этого метода (объект Р1 является получателем метода Ro)
Если нужно изменить поле объекта после создания, то можно использовать оператор присваивания, например
P1.X = 6; // непосредственная изменение значения поля
Во многих случаях прямая изменение поля может быть некорректной. Например, для объектов D 1, D 2 класса TDate (календарные даты) с полями Year, Month, Day:
D1.Month = 13; D2.Day = 32; // некорректно!
Поэтому, как правило, значения полей класса могут изменять только методы данного класса (или дочерних классов).Для корректного доступа к полям класса обращаются через свойства (англ. Property):
property <имя свойства>: <тип>
read <имя поля или метода для чтения>
write <имя поля или метода записи>
default <значение по умолчанию>;
Метод для чтения — это функция без параметров, которая возвращает значение с типом свойства (например GetMonth, GetDay).Также эту функцию называют селектором.
Метод записи — это процедура, которая изменяет значение определенного поля при определенных условиях (SetMonth, SetDay).Также эта процедура называется модификатором.Значение является переменная с типом поля.
Поля и методы для чтения или записи объявляются перед описанием свойства, в описании только указываются их названия.
Значение по умолчанию — это определенное значение свойства, которое задается при создании объекта (для полей Month и Day может быть равным 1).
пример:
view plaincopy to clipboardprint?
- type TDate = class
- private
- aDay, aMonth, aYear: integer
- protected
- procedure SetDay (value: integer);
- // …
- published
- property Day: integer read aDay
- write SetDay
- default 1;
- end;
- procedure TDay.SetDay (value: integer);
- begin
- if value in [1..31]
- aDay = value;
- end;
type TDate = class
private
aDay, aMonth, aYear: integer
protected
procedure SetDay (value: integer);
// …
published
property Day: integer read aDay
write SetDay
default 1;
end;
procedure TDay.SetDay (value: integer);
begin
if value in [1..31]
aDay = value;
end;
Свойства — это еще один способ управлять доступом к полям класса (рядом с директивами private, protected, public, published).
присвоение объектов
У оператора присвоения возможны две семантики:
— семантика копирования;
— семантика указателей.
В первом случае (для всех переменных, кроме объектов и указателей) содержание правой части выражения копируется в содержание левой части (создается копия в памяти).
Во втором случае (для объектов и указателей) левая часть будет указывать на содержание правой части (копия в памяти не создается).
пример:
view plaincopy to clipboardprint?
- var P1, P2: TPoint;
- P1 = TPoint.Create (3, 4); // P1.X = 3; P1.Y = 4;
- P2 = TPoint.Create (5, 7); // P2.X = 5, P2.Y = 7;
- P1 = P2; // P1.X = 5, P1.Y = 7;
- X: = 10; // P2.X = 10; P1.X = 10;
var P1, P2: TPoint;
P1 = TPoint.Create (3, 4); // P1.X = 3; P1.Y = 4;
P2 = TPoint.Create (5, 7); // P2.X = 5, P2.Y = 7;
P1 = P2; // P1.X = 5, P1.Y = 7;
P2.X: = 10; // P2.X = 10; P1.X = 10;
В результате присвоения объект P1 будет указывать на содержание объекта P2. Предыдущий содержание объекта P1 стал недосягаемым.
Для создания копии объекта, как правило, описывается и реализуется специальный метод Assign, который делает присвоении каждого поля отдельно по новому указателю.
P1.Assign (P2) // P1 = P2
Проверка на равенство
При сравнении двух переменных, аналогично к присвоению есть две семантики: копирование и указателей.
Для чисел и символьных переменных условием равенства является одинаковое побитовое представление в памяти (семантика копирования).
Для переменных составных типов используется равенство элементов. Возможна ситуация, когда: а = b, но b ≠ а (когда переменная b содержит больше элементов, чем переменная а).
пример:
а — точка в двумерном пространстве, b — точка в трехмерном пространстве.
Для объектов равенство достигается, когда существует равенство указателей (семантика указателей).
If P1 = P2 then
{…}
Альтернативная проверка на равенство (для объектов с различными указателями) может быть реализована с помощью специального метода Equals.
If P1.Equals (P2) then
{…}
уничтожение объектов
Объекты — динамические переменные, которые создаются и уничтожаются во время работы программы (run-time), поэтому уничтожение объекта предусматривает освобождение памяти.С этой целью используют специальный метод — деструктор (обозначается ключевым словом destructor).Как правило, этот метод называется Destroy.
Кроме деструктора в описании класса обычно вводится метод Free, который проверяет переменная Self важно nil.Для пустая объекта вызывается деструктор.
Пример.
procedure TPoint.Free;
begin
if Self <> nil then Destroy;
end;
При этом автоматического определения значения объектной переменной в nil не происходит.
управление памятью
Для освобождения памяти, которая выделяется под объекты, которые больше не нужны, возможны 3 способа:
- Ручная освобождения (средствами языков программирования);
- «Автоматическое уборка мусора» (англ. Аutomatic garbage collection).Под «мусором» понимают объекты, содержание которых стал недосягаемым, например, вследствие присвоения. Для разных операционных систем разработаны специальные процедуры, которые отслеживают эти объекты с определенными временными интервалом и уничтожают.
- Каждому объекту при создании назначается владелец (другой объект), который руководит процессом освобождения памяти.(Например, форма является владельцем всех объектов, находящихся на ней).
Типичные ошибки при освобождении памяти
- Попытка использовать память, которая еще не выделена;
- Выделенная память никогда не освобождается;
- Память звильняюеться двумя независимыми процедурами;
- Попытка использовать уже освобожденную память.