
- •12.1. Класи й об’єкти. Основні поняття
- •12.2.Опис класів і об’єктів
- •12.3. Складові класів
- •12.4. Поняття успадкування
- •12.4. Поліморфізм. Віртуальні та динамічні методи
- •12.5. Структура опису класу
- •13. Класи загального призначення
- •13.1. Клас exception –- обробки виключень
- •13.2. Клас tlist – списки
- •13.3. Класи tstrings, tstringlist – набори рядків й об’єктів
12.3. Складові класів
Поля. Полями називаються інкапсульвані у класі дані. Поля можуть бути будь-якого типу, у тому числі - класами, наприклад:
Type
TMyClass = class
alntField: Integer;
aStrField: String;
aObjField: TObject;
end;
Кожний об'єкт отримує унікальний набір полів, але загальний для всіх об'єктів даного класу набір методів і властивостей. Фундаментальний принцип інкапсуляції вимагає звертатися до полів тільки за допомогою методів і властивостей класу. Однак в Object Pascal дозволяється звертатися до полів і прямо:
Var
aObject: TMyClass;
begin
aObject.alntField := 0;
aObject.aStrField := 'Рядок символів';
end;
Клас-нащадок успадковує всі поля всіх своїх предків і може доповнювати їх своїми, але він не може перевизначати їх або вилучати. Таким чином, чим нижче в дереві ієрархії розташовується клас, тим більше даних одержують у своє розпорядження його об'єкти.
Методи. Інкапсульвані у класі процедури й функції називаються методами. Заголовки методів описуються у класі, а їх програмний код розміщується за межами класу. Для реалізації методів класу використовуються уточнені імена іменем класу до якого вони належать. Наприклад,
Type //Вимірювач дискового простору
TDiskGauge=class
DriveLetter:char; {Буква дисководу}
{Критичний процент вільного простору}
PercentCritical:integer;
{Повертає об’єм вільного простору на диску}
Function GetPercentFree:integer;
{Перевіряє стан ресурсу і видає звукове
повідомлення}
Procedure CheckStatus;
end;
Реалізація методів у класі TDiskGauge:
Function TDiskGauge.GetPercentFree:integer;
Var Drive:Byte;
begin
Drive:=ord(DriveLetter)-ord(‘A’)+1;
Result:=DiskFree(Drive)*100 div
DiskSize(Drive);
end;
Procedure TDiskGauge.CheckStatus;
begin
if GetPercentFree <= PercentCritical then
Beep;
end;
У методах звернення до полів та інших методів здійснюється як до звичайних змінних і підпрограм без уточнення екземпляру об’єкту. Таке спрощення досягається шляхом використання у межах методу змінної Self. Практично Self є неявним параметром, який передається у метод при його виклику. Цей параметр вказує екземпляр об’єкту до якого застосовується даний метод. Тобто:
Procedure TDiskGauge.CheckStatus
(Self: TDiskGauge);
begin
with Self do
if GetPercentFree <= PercentCritical then
Beep;
end;
Змінна Self рідко використовується у явному вигляді. Її використовують тільки тоді коли може виникнути неоднозначність для компілятора, наприклад при використанні однакових імен для локальних змінних і полів об’єкту.
Поля і методи класу можна викликати тільки після створення об'єкту за допомогою виклику конструктора, тому що конструктори розподіляють об'єкт у динамічній пам'яті й роблять і створюють вказівник на цей об'єкт.
До складу будь-якого класу входять два спеціальних методи - конструктор і деструктор. У класі TObject ці методи називаються Create й Destroy, так само вони називаються в переважній більшості його нащадків. Конструктор розподіляє об'єкт у динамічній пам’яті й поміщає адресу цієї пам'яті в змінну Self, що автоматично оголошується у класі. Деструктор вилучає об'єкт із купи. Звертання до конструктора повинне випереджати будь-яке звертання до полів і деяких методів об'єкту. За своєю формою конструктори й деструктори є процедурами, але оголошуються за допомогою зарезервованих слів Constructor й Destructor. Наприклад,
Type
TDiskGauge=class
DriveLetter:char;
PercentCritical:integer;
Constructor Create;
Destructor Destroy;
. . . . . . . .
end;
Constructor TDiskGauge.Create;
begin
DriveLetter:=’c’;
PercentCritical:=10;
end;
Конструктор може мати параметри в яких передаються початкові значення полів об’єкту. Конструктор може застосовуватися як до класу так і до об’єкту. Якщо конструктор застосовується до класу
DiskGauge:= TDiskGauge.Create;
то виконується така послідовність дій:
у динамічній пам’яті виділяється місце для нового об’єкту;
виділена пам’ять ініціалізується : числові поля нулями, символьні рядки порожнім значенням, а вказівники і об’єкти значенням NIL;
виконуються дії конструктора;
вказівник на створений об’єкт повертається в якості значення конструктора, тип значення співпадає з типом класу до якого він застосований(в нашому приклад це тип TDiskGauge).
Якщо конструктор застосовується до об’єкту
DiskGauge.Create;
то новий об’єкт не створюється, а відбувається переініціалізація полів існуючого об’єкту. У цьому випадку конструктор не повертає ніякого значення.
Деякі методи можуть викликатися без створення й ініціації об'єкта. Такі методи називаються методами класу, вони оголошуються за допомогою за допомогою зарезервованого слова class. Наприклад,
Type
TMyClass = class(TObject)
class Function GetClassName: String;
end;
Var
S: String;
begin
S := TMyClass.GetClassName;
end;
Деструктор вилучає із динамічної пам’яті об’єкт до якого він застосовується
DiskGauge. Destroy;
в результаті виконується заданий код деініціалізації, звільняється динамічна пам’ять, яку займав об’єкт. У тілі деструктора повинні знищуватися вбудовані об’єкти і динамічні дані, створені конструктором.
У базовому класі TObject визначений метод Free, що спочатку перевіряє дійсність адреси об'єкта й лише потім викликає деструктор Destroy. Звертання до деструктора об'єкта буде помилковим, якщо об'єкт не створений конструктором, тому для знищення непотрібного об'єкта варто викликати метод
DiskGauge.Free;
Властивості. Це спеціальний механізм класів, що регулює доступ до полів. Властивості оголошуються за допомогою зарезервованих слів property, read й write (слова read й write вважаються зарезервованими тільки в контексті оголошення властивості).
Звичайна властивість пов'язана з деяким полем і вказує ті методи класу, які повинні використовуватися для запису в це поле або читання з нього. Властивість може й не зв'язуватися з полем. Фактично вона описує один або два методи, які здійснюють деякі дії над даними того ж типу, що й властивість. При цьому значення властивості записується і читається із деякої внутрішньої змінної.
Якщо необхідно, щоб поле було доступним тільки для читання або тільки для запису, то слід опустити відповідно частину read або write. Наприклад,
Type
TDiskGauge=class
FDriveLetter:char;
FPercentCritical:integer;
FIntField: Integer;
Function GetPercentFree:integer;
Procedure CheckStatus;
{Процедури і функції для запису і читання властивостей}
Procedure SetPercentCritical
(Percent:integer);
Function GetField: Integer;
Procedure SetField(Value: Integer);
{Властивість пов’язана з полем}
Property PercentCritical: Integer read FPercentCritical write SetPercentCritical;
{Властивість не пов’язана з полем}
Property IntegerValue: Integer
read GetField write SetField;
end;
У контексті програми властивість поводиться як звичайне поле. Наприклад, можна написати такі оператори:
var //Об'єкт класу
DiskGauge: TDiskGauge;
Value: Integer;
Begin
{Перед звертанням до поля або властивості обов'язково створити об’єкт за допомогою конструктора}
DiskGauge:TDiskGauge.Create;
{Присвоєння змінній значення властивості }
Value := DiskGauge.PercentCritical;
{Присвоєння змінній значення поля}
Value := DiskGauge.FPercentCritical;
{Присвоєння властивості значення змінної}
DiskGauge.PercentCritical:= Value+10;
{Присвоєння властивості значення за допомогою методу}
DiskGauge.SetPercentCritical(Value+10);
aClass.IntegerValue := 0;
Value := aClass.IntegerValue;
DiskGauge.Destroy; // Вилучення непотрібного об'єкту
end;
Якщо немає необхідності в спеціальних діях при читанні або запису властивості, замість імені відповідного методу можна вказувати ім'я поля.
Методи читання і запису властивостей підкоряються певним правилам. Метод читання властивості є функцією, яка повертає значення того ж типу що і властивість. Метод запису властивості обов’язково процедура. Наприклад,
Procedure TDiskGauge.
SetPercentCritical(V:integer);
begin
if (v>=0)and(v<=100) then begin
FPercentCritical:=v; Beep; end;
end;
Метод SetPercentCritical записує значення властивості PercentCritical і створює у якості побічного ефекту звуковий сигнал – процедура Beep.