Статичні методи.

Поліморфізм - це можливість мати декілька методів з одним і тим же ім'ям для різних об'єктів однієї ієрархії, тобто засіб для розвитку об'єктів в нащадках. Воно реалізується тим, що об'єкт-нащадок може перевизначати, тобто замінювати методи предка на нових з тими ж іменами. Який з методів виконуватиметься при зверненні до методу із заданим ім'ям, визначається типом об'єкту (предок або нащадок) і використовуваного методу. Методи об'єктів по способах їх перевизначення можуть бути статичні, віртуальні і динамічні (підклас віртуальних). Відповідно до цього процес установки взаємозв'язку об'єктів і методів може бути: § раннім - під час компіляції - для статичних методів; § пізнім - під час виконання програми (виклику методу) для віртуальних методів. Статичні методи: По замовчуванню всі методи статичні. Всі раніше розглянуті методи -статичні. Таке найменування методів пов'язане з тим, що визначення і розміщення посилань на них (для виклику методів) проводиться на етапі компіляції і на весь час виконання програми. Це – попереднє скріплення.
     

Список формальних параметрів статичних методів може бути різним у методу предка і методів нащадків, перевизначений (замінюючий) цей метод предка.

Із статичним методом пов'язаний спосіб спадкоємства. Якщо в оголошенні нащадка з'являється метод з тим же ім'ям, що і у предка, то в цьому типі і у всіх його нащадках цей метод буде перевизначений. Таким чином, нащадки можуть використовувати перевизначені ними методи предка. Предок може викликати тільки свої методи; методи нащадків для нього недоступні. Таким чином, при використанні статичних методів поліморфізм розповсюджується від поточного рівня ієрархії вниз, до нащадків.

Дії компілятора при обробці методів ієрархії об'єктів для статичних методів:

1) при виклику методу компілятор встановлює тип об'єкту, що викликає
метод;

2) потім він шукає метод в межах цього типу; знайшовши його, компілятор призначає виклик цього методу;

3) якщо метод не знайдений, то компілятор розглядає тип безпосереднього предка і шукає метод в його оголошенні:

a) якщо метод з таким ім'ям знайдений, формується виклик методу цього
предка;

b) якщо метод не знайдений в типі найближчого предка, компілятор переходить
до типу предка, наступного в ієрархії предків; і так до тих пір, поки
не буде знайдений викликаний метод;

c) якщо компілятор, дійшовши до верхнього рівня ієрархії, не знайде метод,
він видасть повідомлення про помилку номер 44 періоди компіляції:

Field identifier expected - очікується ідентифікатор поля.

Це повідомлення видається, якщо ідентифікатор не відповідає імені поля змінної типу RECORD або типу OBJECT.

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

Лістинг 1. Виклики статичних методів предка і нащадка.

Program novirt1;

Uses Crt;

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

Fl1 : integer; { - поле }

Procedure Met1; { - методи }

Procedure Met2;

End;

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

Procedure Met2; { - заміна статичного методу }

End;

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

Procedure ObjName1.Met1;

Begin Met2; { - виклик тільки методу Objname1.Met2!!}

End;

Procedure ObjName1.Met2;

Begin

FL1 := 12;

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, 'Inovirt.res');

Rewrite (Output);

Writeln (‘ОБ'ЄКТИ, СТАТИЧНІ МЕТОДИ’ );

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

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

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

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

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

V2.Met1; { - викликається метод Met1 для екземпляра V2 - нащадка; Met1 викликає метод Objname1.Met2 - предка, а не Objname2.Met2 - нащадка - в цьому - обмеження }

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

Close (Output);

End.

Мал. 2 Схема обмеження виклику перевизначених статичних методів

З нього видно істотне обмеження статичних методів: якщо метод (Met1 об'єкту Objname1) предка викликає інші методи (Met2), то це можуть бути тільки методи предка (objnamel .Met2), навіть якщо нащадок має свої власні методи з таким же ім'ям методу (objname2 .Met2). У прикладі лістингу оператор V2.Met1; викликає виконання методу Objnamel.Met1, який викликає метод Objnamel .Met2, не дивлячись на те що тип Objname2 має свій власний метод Objname2.Met2. Це відбувається тому що зв'язок об'єкту з методом проводився на етапі компіляції. Схематично це представлено на малюнку.