Методическое пособие 555
.pdfобъектная_переменная.имя_свойства := выражение;
В PascalABC.Net при описании свойства вместо getметода можно указать имя соответствующего поля:
property имя_свойства: тип read имя_поля write set_метод;
Вэтом случае объявлять функцию чтения нет необходимости. Рассмотрим следующий пример:
type
Person = class private
nm: string; //имя ag: integer; //возраст
procedure setAge(a: integer); begin
if a>0 then ag := a
else
a := 0;
end;
function getId: string; begin
getID := nm + IntToStr(ag); end;
public
property Age: integer read ag write setAge;
property Name: string read nm; property Id: string read getId;
end;
var p: Person;
141
begin
p := new Person;
p.Age := 58;//Изменение значения свойства
Age
//будет вызвана процедура
SetAge
writeln(p.Id); //будет вызвана функция GetId
end.
В этом примере класс person содержит два приватных поля nm (имя) и ag (возраст), приватные методы setAge и getId, и три публичных свойства: Age, Name и Id. Свойства Age и Name ассоциированы с полями nm и ag. Метод SetAge является set-методом для свойства Age и изменяет значение ассоциированного с этим свойством поля ag. Роль get-методов для свойств Age и Name играют соответственно поля ag и nm – значения этих полей будут подставлены в случае доступа к свойствам на чтение. Метод getId является getметодом для свойства Id, данный метод возвращает строку, являющуюся суммой строк nm и IntToStr(ag) (имя и возраст).
1.4. Наследование классов и полиморфизм
Класс может быть унаследован от другого класса. Класс, от которого наследуют, называют базовым классом (надклассом, предком), а класс, который наследуется, называется производным классом (подклассом, потомком). При описании класса его базовый класс указывается в скобках после слова class.
При наследовании все поля, методы и свойства базового класса переходят в производный класс, кроме этого, могут быть добавлены новые поля, методы и свойства и переопределены (замещены) старые методы.
142
Например:
type
BaseClass = class a: Real; procedure p;
procedure r(i: Integer); end;
MyClass = class(BaseClass) procedure r(i: Integer);
end;
В этом примере для класса BaseClass имя классапредка не указано, поэтому он наследуется от класса Object (предка всех классов).
Класс MyClass наследуется от класса BaseClass, при этом поле a и метод p добавляется в класс MyClass. Метод r класса-потомка MyClass имеет то же имя, что и в классе-предке BaseClass. При этом происходит переопределение метода: при вызове метода r для объекта класса MyClass выполняется метод, определенный в классе
MyClass.
Если после переопределения метода в классе-потомке требуется вызвать метод базового класса, то используется служебное слово inherited (унаследованный).
1.5.Перегрузка методов
ВPascalABC.Net можно объявлять подпрограммы с одним именем, но разным количеством или типами параметров. Имена таких процедур и функций называются перегружен-
ными.
При вызове перегруженной процедуры или функции компилятор выберет ту версию, у которой типы формальных параметров совпадают с типами фактических или наиболее близки к ним. Например, если имеются процедуры
143
procedure p(b: Integer); procedure p(r: Real);
при вызове p(1.0) будет выбрана перегруженная процедура с параметром типа Real, а при вызове p(1) будет выбрана перегруженная процедура с параметром типа Integer.
Если выбор из перегруженных процедур невозможен (ни одна не подходит или обе подходят одинаково хорошо), то компилятор сообщит об ошибке.
Если класс-потомок содержит метод, имя которого совпадает с одним из методов базового класса, но число и/или тип параметров отличаются, то этот метод будет не переопределять (как это описано в п. 1.4), а перегружать метод базового класса.
Как и переопределение методов, перегрузка является одним из механизмов реализации принципа полиморфизма.
Отметим, что перегружать можно не только подпрограммы, но и операции. Например, можно перегрузить арифметический оператор + таким образом, чтобы он позволял складывать не только числа, но и объекты некоторого класса. Подробнее о перегрузке операций можно прочитать в справочной системе PascalABC.Net (Справка->Справочник по языку->Классы->Перегрузка операций).
1.5. Конструкторы и деструкторы
Для создания и удаления объектов используются специальные методы, называемые конструкторами и деструкто-
рами.
Конструктор представляет собой функцию, создающую объект в динамической памяти, инициализирующую его поля и возвращающую указатель на созданный объект. Этот указатель обычно сразу присваивается переменной типа класс. При описании конструктора вместо служебного слова function используется слово constructor, тип возвращаемого значения не указывается. Например:
144
type
Person = class private
nm: string; //имя ag: integer; //возраст
public
constructor Create(name: Strig; age: Integer;)
end;
constructor Person.Create(name: string; age: integer);
begin
nm := name; //инициализация полей объекта ag := age;
end;
Для вызова конструктора можно использовать два способа (первый – в стиле языка Object Pascal, второй – в стиле C#):
1) var p: Person;
p:= Person.Create('Иванов',20);
2)var p: Person;
p:= new Person('Иванов',20);
В языке ObjectPascal при удалении объекта вызывается процедура-деструктор, уничтожающая объект и освобождающая динамическую память, выделенную ранее под этот объект. Ее описание имеет вид:
destructor Destroy; begin
...
end;
145
В PascalABC.NET деструктор не играет никакой роли – здесь память управляется т.н. сборщиком мусора – специальным процессом, который периодически освобождает память, удаляя из нее те объекты, которые в дальнейшем не используются приложениями.
2. Практическая часть
Задание 1. Создать класс VehicleClass (англ. vehicle
–транспортное средство), содержащий:
–приватные поля Liters (объем цилиндров в литрах), Vx (количество цилиндров), Horses (мощность двигателя в л.с.), RPMs (обороты двигателя в минуту);
–публичные свойства EngineSize, Cylinders, HR,
RPM, служащие интерфейсами для доступа к полям Liters, Vx, Horses и RPMs соответственно;
–приватные set -методы для указанных выше свойств.
Решение. Описание соответствующего класса представлено ниже.
type
//Класс транспортного средства
VehicleClass = class private
Liters: Real; {Объем цилиндров в литрах} Vx: Integer; {Количество цилиндров} Horses: Integer; {Мощность двигателя в л.с.} RPMs: Integer; {Обороты двигателя в минуту}
//Set-методы
procedure SetEngineSize(ltrs: Real); begin
Liters := ltrs; end;
procedure SetCylinders(cyl: Integer); begin
146
Liters := cyl; end;
procedure SetHP(hpwr: Integer); begin
Horses := hpwr; end;
procedure SetRPM(RevPerMin: Integer); begin
RPMs := RevPerMin; end;
public
//Свойства
property EngineSize: Real read Liters
write SetEngineSize; property Cylinders: Integer read Vx
write SetCylinders; property HP: Integer read Horses write SetHP; property RPM: Integer read RPMs write SetRPM;
end;
Задание 2. Добавьте в класс VehicleClass публичную функцию Describe, которая возвращает строку с описанием объекта класса VehicleClass. Пример содержания такой строки:
’1.6 л., V4, 106 л.с., 5500 об/мин ’
Решение. Описание функции Describe представлено ниже. Добавьте это описание в публичную секцию класса
VehicleClass.
function Describe: string; begin
Describe := FloatToStr(EngineSize) + 'л., V' + IntToStr(Vx) + ', ' +
IntToStr(Horses) + ' л.с.,' + IntToStr(RPMs) + ' об/мин';
end;
147
Задание 3. Добавьте в класс VehicleClass публичную процедуру SetAll, устанавливающую все свойства объекта данного класса.
Решение. Добавьте следующее описание процедуры SetAll в публичную секцию класса VehicleClass.
procedure SetAll(eng: Real; cyl, hpwr,rev: Integer);
begin
Liters := eng; Vx := cyl; Horses := hpwr; RPMs := rev;
end;
Задание 4. Создайте новый класс MotorcycleClass (класс мотоцикла), дочерний по отношению к классу VehicleClass (все свойства и методы класса-предка будут унаследованы). Добавьте в новый класс его собственные методы и свойства:
–приватные поля TankSize (объем топливного бака в литрах) и ExtColor (цвет кузова);
–публичные свойcтва FuelTank и Exterior, слу-
жащие интерфейсами для доступа к полям TankSize
иExtColor соответственно;
–приватные set -методы для указанных выше свойств;
–публичную функцию Describe, переопределяющую одноименную функцию класса-предка VehicleClass и выводящую информацию об объекте в виде строки, например
3.4л., V5, 52 л.с.,5900 об/мин,
16.9литров в баке, Цвет кузова - черный
-публичную процедуру SetAll, перегружающую одноименную процедуру класса-предка VehicleClass и задающую все свойства объекта класса MotorcycleClass.
148
Решение. Описание класса MotorcycleClass и его методов представлено ниже. Добавьте это описание в программу.
//Класс мотоцикла
MotorcycleClass = class(VehicleClass) private
TankSize: Real;//Объем топливного бака в литрах
ExtColor: String; //Цвет кузова
//Set методы
procedure SetCapacity(tank: Real); begin
TankSize := tank; end;
procedure SetExtColor(color: String); begin
ExtColor := color; end;
public
//свойства
property FuelTank: Real read TankSize write SetCapacity;
property Exterior: String read ExtColor
write SetExtColor; //методы (полное описание – позднее)
function Describe: String;
procedure SetAll(eng: Real; cyl, hpwr,
rev: Integer; tank: Real; color: String);
end;
//Полный текст методов класса MotorcycleClass function MotorCycleClass.Describe: String; var
tank: String; begin
149
//Вызов метода Describe класса-предка
//(ключевое слово inherited) Result := inherited Describe;
//Преобразуем число TankSize в строку и //поместим эту строку в переменную tank
Str(TankSize:4:1, tank);
//Формируем строку описания объекта (мотоцикла)
Result := Result + ', ' + tank +
' литров в баке, ' + 'Цвет кузова - ' + ExtColor; end;
procedure MotorcycleClass.SetAll(eng: Real; cyl, hpwr, rev: Integer; tank: Real; color: String);
begin
//Вызов метода SetAll родительского класса inherited SetAll(eng, cyl, hpwr, rev) ;
//Дополнительно задаем свойства, //отсутствовавшие в родительском классе
TankSize := tank; ExtColor := color;
end;
Задание 5. Добавьте в класс MotorcycleClass публичный метод (процедуру) Initialize, который инициализирует объект данного класса путем присвоения всем свойст-
вам значений по умолчанию. |
|
|
|
|
Указание. |
Добавьте |
в |
секцию |
public |
класса MotorcycleClass метод |
|
|
procedure Initialize;
Полное описание метода создайте самостоятельно (в теле процедуры Initialize следует вызвать метод SetAll с параметрами, задающими значения по умолчанию для объекта данного класса).
150