Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекція 5.docx
Скачиваний:
1
Добавлен:
18.11.2019
Размер:
326.67 Кб
Скачать

Object not initialized - об'єкт не ініціалізував.

Оскільки директива {$R+} уповільнює виконання програми, після відладки директиву треба видалити; за умовчанням працює директива {$R->.

У об'єкті може бути скільки завгодно конструкторів. Конструктор не може бути віртуальним. Конструктор може бути тільки статичним і може бути перевизначений. Конструктори успадковуються так само, як і інші статичні методи. З конструктора можна викликати і віртуальні методи.

Метод конструктора може бути і порожнім, оскільки основна інформація міститься не в тілі конструктора, а пов'язана з його заголовком, що містить слово Constructor.

Наприклад:

Constructor TA.TNIT ;

Begin

End;

Конструктору прийнято давати ім'я INIT. На практиці в якості конструктора який використовує метод, який встановлює деякі початкові значення екземпляра об'єкту. У конструкторі може відбуватися виділення ОП з купи, якщо поля даних динамічні, і необхідна ініціалізація полів даних (у тому числі і виклики конструкторів-предків для успадкованих полів).

Приклад програми з використанням віртуальних методів даний в лістингу2. Це варіант програми лістингу 1, але з віртуальним методом Met2.

Лістинг 2. Використання віртуальних методів.

Program virt1; {$F+,R+}

Uses Crt;

Type ObjName1 = object { - оголошення об'єкту-предка }

Fl1 : integer;

Constructor Met1; { - конструктор }

Procedure Met2; Virtual; { - віртуальний метод }

End;

ObjName2 = object(ObjName1) {- оголошення нащадка}

Procedure Met2; Virtual; { - віртуальний метод }

End;

{ Методи об'єкту Objname1 }

Constructor ObjName1.Met1;

Begin

Fl1 := 12;

Met2; { - виклик Met2 з конструктора }

End;

Procedure ObjNamel.Met2;

Begin

Writeln ('Працює метод ObjName1.Met2: FL1 = ', Fl1)

End;

{-----------------Методи об'єкту Objname2-------------------------------------------}

Procedure ObjName2.Met2;

Begin

Fl1 := 34;

Writeln ('Працює метод ObjName2.Met2: FL1 = ', Fl1)

End;

Var V1:ObjName1; {- змінна об'єктного типу - предка }

V2 : ObjName2; { - " " " нащадка }

{ Основна програма }

Begin

ClrScr;

Assign (Output, '2virt.res');

Rewrite (Output);

Writeln ('ОБ'ЄКТИ, ВІРТУАЛЬНІ МЕТОДИ');

Writeln ('Працюємо з VI - екземпляром типу предка');

V1.Met1; { - викликається конструктор Met1 для екземпляра VI - предка }

{ Met1 викликає метод Objname1.Met2 - предка }

V1.Met2; { - безпосередньо викликається метод Objname1.Met2; }

Writeln ('Працюємо з V2 - екземпляром типу нащадка');

V2.Met1; { - викликається конструктор Met1 для екземпляра V2 - нащадка VI; Met1 викликає метод Objname2.Met2 - нащадка -в цьому гідність віртуальних методів }

V2.Met2 { - безпосередньо викликається метод Objname2.Met2; }

Close. (Output) ;

End.

Кожен екземпляр об'єкту повинен ініціалізуватися окремим викликом конструктора. Не можна ініціалізувати один екземпляр об'єкту і потім привласнювати цей екземпляр іншим, неініціалізованим об'єктам. Інші екземпляри, навіть якщо вони містять правильні дані, не ініціалізують оператором привласнення і заблокують систему при будь-яких викликах їх віртуальних методів.

Наприклад:

Var Obj1, Obj2 : Tobj; { - оголошення змінних }

Begin

Obj1.Init; { - ініціалізація Obj1 }

Obj2 := Obj1; { - неприпустимо до ініціалізації Obj2 за допомогою Obj2.Init; }

End.

Хорошим стилем ООП є використання процедур ініціалізації предків. Тобто якщо нащадок має нову процедуру ініціалізації, то в ній зазвичай спочатку викликається процедура ініціалізації (наприклад, конструктор) безпосереднього предка, а потім виконується своя. Це природний спосіб проїніциалізіровать успадковані поля призначеним для цього методом.

Додаткова можливість виклику методу, безпосередньо успадкованого об'єктом-нащадком, - використання ключового слова Inherited (успадкований) перед ім'ям методу, що викликається.

Наприклад, Obj1 безпосередній предок об'єкту Obj2. До складу Obj1 входить метод Met1. Виклик цього методу об'єкту Obj1 з методу Obj2.Met2 може бути заданий явно у вигляді:

Procedure Obj2.Met2;

Begin Inherited Met1 (A1, A2);

{ Це еквівалентно виклику: Obj1.Met1 (A1, A2); }

End;

При цьому не треба знати ім'я об'єкту-предка (Obj1). Основні правила використання віртуальних методів:

    1. якщо тип об'єкту-предка описує метод як віртуальний, то всі його нащадки, які реалізують свій метод з тим же ім'ям, повинні описати цей метод як віртуальний. Не можна віртуальний метод замінити статичним. Інакше компілятор видасть повідомлення про помилку:

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]