Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по паскалю.docx
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
67.39 Кб
Скачать
  1. Использование экземпляров объекта

Поскольку объект - это тип данных, то для работы с ним мы должны объявить переменную этого типа. Такая переменная в рамках ООП называется экземпляром объекта. Экземпляр объекта в Turbo Pascal может быть объявлен для любого объектного типа иерархии (как для родителя, так и для потомка). Более того, может быть объявлено несколько экземпляров одного и того же объекта. Каждый из таких экземпляров получает "свой" набор свойств. Они ничего "не знают" друг о друге, то есть являются полностью независимыми (по крайней мере, должны таковыми быть).

Экземпляр объекта описывается в разделе описания переменных программы (подпрограммы) следующим образом:

Var

<имя переменной (экземпляр объекта)>:<объектный тип>;

Объявлять можно как единичные экземпляры объектов, так и массивы объектов, записи, содержащие объекты, и даже объекты, содержащие объекты (правда, только в разделе описания типов Type). Единственное, чего нельзя делать, это объявлять файлы объектов:

Var

a: Array [1..10] of TPoint; {Массив объектов - точек}

b = record {Запись, содержащая два объекта}

p1,p2: TPoint;

end;

f : file of TPoint; {Файл объектов - так нельзя}

Type

Rect = object {Объект, поля которого - объекты}

a,b: TLocation;

...

end;

Для нашего примера имеет смысл описать экземпляр объекта TPoint, то есть точку на экране:

Var

Point1: TPoint;

После описания экземпляра объекта программе станут доступными его информационные поля и методы, то есть в программе можно читать и изменять значения полей экземпляра объекта, а также вызывать его методы. Обратиться к полю экземпляра объекта можно следующим способом: указать имя экземпляра, затем через точку имя поля. После чего с полем можно обращаться, как с обычной переменной, например присвоить ему какое-то значение:

Point1.X := 65;

Однако считается плохим стилем программирования прямое обращение к полям экземпляра объекта. Предполагается, что программа не должна ничего "знать" об атрибутах объекта, она только может "просить" экземпляр объекта показать или изменить свои атрибуты за счет использования соответствующих методов. Иначе говоря, программа может только вызывать методы экземпляра объекта. Вызов метода осуществляется синтаксически по тем же правилам, что и вызов "обычной подпрограммы", только перед именем метода надо обязательно написать через точку имя экземпляра объекта:

Point1.Init(150,100,Blue);

В этом примере мы создали объект - точку с координатами X=150 и Y=100 синего цвета (невидимую). Для "проявления" ее на экране необходимо вызвать метод Show:

Point1.Show;

Для перемещения этой точки в новую позицию мы должны вызвать метод MoveTo, для получения текущих координат - GetX, GetY или GetCoords и т.п.

  1. Динамическая память и деструкторы

Экземпляры объектов можно размещать в динамической памяти (куче). Работа с кучей применительно к объектам почти не отличается от работы с кучей применительно к обычным данным. Точно так же необходимо объявить ссылку на объект (переменную ссылочного типа), выделить для нее память в куче, а в конце работы эту память освободить.

Разместим, например, в куче экземпляр объекта TCircle:

Type

PCircle = ^TCircle;

Var

Circ1 : PCircle;

...

Begin

Circ1 := New(PCircle);

или

New(Circ1);

Для работы с экземпляром объекта, расположенного в куче, необходимо проводить (как обычно) операцию разыменовывания указателя, например:

Circ1^.Init(150,200,40,Blue);

Существует расширенный синтаксис процедуры (и функции) New для выделения памяти экземпляру объекта с одновременным вызовом метода-конструктора:

Сirc1 := New(PCircle,Init(150,200,40,Blue));

или

New(Сirc1,Init(150,200,40,Blue));

При работе с динамическими объектами надо очень серьезно подходить к освобождению памяти. Ведь и сам объект в качестве своих полей может содержать указатели и ссылки. Память, занятая этими динамическими данными, должна освобождаться до вызова процедуры Dispose для самого объекта. То есть если память, занятая полями, освобождается в методе Done, то этот метод должен быть вызван до удаления экземпляра объекта из кучи. То, что экземпляр объекта-родителя и экземпляр объекта-потомка являются совместимыми по типу "сверху вниз" (значение экземпляра объекта-потомка может быть присвоено экземпляру объекта-предка с потерей "лишних данных", но не наоборот), при работе с кучей также может привести к неверному освобождению памяти (может быть освобождена "чужая" память). В связи с этим синтаксис процедуры Dispose тоже расширен и позволяет вызывать деструктор объекта до его удаления из кучи:

Dispose(Сirc1,Done);

При таком написании, сначала вызывается деструктор, а затем высвобождается память.

Кстати, назначение деструктора как разновидности процедуры - следить за тем, чтобы высвобождалась соответствующая память. То есть деструктор - это, как и конструктор, специальный вид метода, который по-другому еще называют "сборщиком мусора".