Особенности использования объектов
Значение одной объектной переменной можно присвоить другой. При этом объект не копируется в памяти, а вторая переменная просто связывается с тем же объектом, что и первая:
Листинг 1.10
Var
A, B: TMySimpleClass; // Переменные A и B не связаны с объектом
Begin
A := TMySimpleClass.Create; // Связывание переменной A с новым объектом
// Переменная B пока еще не связана ни с каким объектом
B := A; // Связывание переменной B с тем же объектом, что и A
// Теперь обе переменные связаны с одним объектом
B.Free; // Уничтожение объекта
// Теперь A и B не связаны ни с каким объектом
end;
Объекты могут выступать в программе не только в качестве переменных, но также элементов массивов, полей записей, параметров процедур и функций. Кроме того, они могут служить полями других объектов. Во всех этих случаях программист фактически оперирует указателями на экземпляры объектов в динамической памяти. Следовательно, объекты изначально приспособлены для создания сложных динамических структур данных, таких как списки и деревья. Указатели на объекты для этого не нужны.
С объектами-наследниками можно работать так же как и с объектами-родителями. Это, например, позволяет держать в одном массиве родственный объекты разных классов, а не создавать несколько отдельных массивов.
Пусть перед нами стоит задача рисования некоторых геометрических фигур. Возьмём прямоугольник и круг. Создадим для них два класса, наследуемых от абстрактного класса фигура. Далее поместим объекты обоих классов в один массив и будем по очереди вызовать для каждого объекта метод Draw().
Листинг 1.11
Type
TFigure= class(TObject)
procedure Draw();virtual;abstract;
end;
TRectangle = class(TFigure)
fx,fy:integer;
procedure Draw();override;
end;
TCircle = class(TFigure)
fR:integer;
procedure Draw();override;
end;
…
var A:array [1..3] of TFigure;
i:integer;
…
procedure TRectangle.Draw;
Begin
inherited;
ShowMessage('Rectangle');
end;
procedure TCircle.Draw;
Begin
inherited;
ShowMessage('Circle');
end;
//данный код поместить в обработчик нажатия кнопки
A[1]:=TRectangle.Create();
A[2]:=TCircle.Create();
A[3]:=TRectangle.Create();
for i:=1 to 3 do A[i].Draw();
После точки в такой конструкции будут выводиться только те поля и методы, которые имеются в родительском классе. Если нужно обратиться к элементам наследников, то необходимо использовать приведение типов:
TRectangle(a[1]).x:=2;
Если заранее не известно какого типа текущий обрабатываемый элемент, то можно внести дополнительное поле в класс родителя, которое будет давать эту информацию.
Расширенное описание класса.
Помимо использования обычных полей (переменных) и методов (функций) в objectpascal встречаются их некоторые модификации. Это свойства, события, обработчики событий. В общем виде класс имеет следующую структуру (пример):
Листинг 1.12
TMyRectangle = class(TObject)
Public //раздел конструкторов и деструкторов
constructor Create; overload; //конструкторпоумолчанию
constructor Create(width,height: integer); overload; //параметрич. конструктор
Protected //в защищённом разделе находятся поля объекта
Fw: integer; //ширина - поле
FhTeg: integer; //высота - поле
Protected //раздел методов для работы со свойствами
procedureSetwidth(width:integer); //установка значения ширины - метод
function Getwidth: integer; //получение значения ширины - метод
procedureSetHeight(height:integer); //установка значения ширины - метод
function GetHeight: integer; //получение значения ширины - метод
Public //разделсвойств
property width: integer read getwidth write setwidth default 100; //свойствообъекта - ширина
property height: integer read getHeight write setHeight default 50; //свойствообъекта – высота
Protected //закрытый раздел для внутренних методов
function FindRound: real; //расчётскругления - метод
Public //раздел открытых методов для доступа к классу из вне
procedure Draw (canvas: TCanvas); //рисование - метод
Public //обработчикивнешнихсобытий
procedure WMKeyDown(var Msg: TWMKeyDown); message WM_KEYDOWN; //нажатиеклавиши
Protected //внутренние события
FOnResizeEvent: TNotifyEvent; //возникает при изменении размеров
Public//published если это компонент - внешнее отображение события
property OnResize: TNotifyEvent read FOnResizeEvent write FOnResizeEvent;