Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
vidpovidi_OOP.doc
Скачиваний:
21
Добавлен:
23.02.2016
Размер:
281.6 Кб
Скачать

19. Реалізація наслідування мовою Object Pascal.

1) Посилання на ім’я суперкласу розміщується в дужках:

Type

TqueueWithMax = class(Tqueue)

private

max: Integer; //Опис додаткових полів класу

….

public

Constructor TqueueWithMax.Create(Max: Integer);

…. //Опис додаткових методів класу

end;

Implementation

…. //Опис методів

2) Опис конструктора сабкласу містить посилання на конструктор суперкласу за допомогою слова Inherited:

public Constructor TqueueWithMax.Create(Max: Integer); //Опис

//конструктора

Constructor TqueueWithMax.Create ;

begin

Inherited Create; //Виклик конструктора суперкласу

max

end;

//Головна програма

var q: TqueueWithMax;

begin

q:= TqueueWithMax.Create(2); // створення об’єкта сабкласу

end;

3) Перевизначення метода потребує, по-перше, щоб це було дозволено ще в суперкласі за допомогою слова virtual (або dynamic), і , по-друге, щоб в сабкласі було указано перевизначення метода за допомогою слова override .

Procedure seize; virtual; //в описі суперкласу

….

Procedure seize; override; //в описі сабкласу

Зауваження: різниця між virtual і dynamic полягає в тому, що virtual указує на внесення метода в таблицю віртуальних методів (оптимізації по швидкості), а dynamic – на те, що метод знаходиться за ім’ям суперкласу (оптимізація по розміру програмного коду). Переважне використання virtual. Слово dynamic рекомендується використовувати при складних ієрархічних зв’язках супер та сабкласів.

4) Оператор is дозволяє перевірити приналежність об’єкта до класу:

if q is TqueueWithMax then….;

5) Існує можливість виклику метода, що належить підкласу об’єкта, за допомогою оператора as:

if q is TqueueWithMax // змінна q указує на об’єкт типу Tqueue

then

(q as TqueueWithMax).seize; //приведення типу об’єкту до TqueueWithMax

Зауваження: в окремих випадках приведення типів неможливо, тому може бути помилка.

Оператори is, as використовуються для перевірки приналежності об’єкта, що належить суперкласу і передається у якості параметра, підкласу.

6) Для опису абстрактних методів використовується слово abstract:

Procedure draw; virtual ; abstract; //процедура буде перевизначена

// в сабкласах

Зауваження: абстрактний метод завжди являється також віртуальним!

20. Реалізація наслідування мовою C++.

1) Наслідування указується при описі класу через двокрапку. Якщо суперкласів декілька (в С множинне наслідування допускається), то суперкласи указуються через двокрапку:

class Docent: Science_employee, Teacher_employee

{

…..

}

При указуванні батьківського класу, можливо указується ключ доступу private, public, protected. За замовчуванням для класів вважається, що ключ доступу private. Але всі елементи суперкласу, що відмічені private, НЕ доступні сабкласу не залежно від ключа доступа.

private - всі елементи суперкласу не доступні (доступ тільки через методи), тобто всі (private, public, protected) стають private;

protected - всі елементи суперкласу доступні для сабкласу, окрім елементів private (ті, що були public, стають protected, а для інших не змінюється)

public - всі елементи суперкласу мають в сабкласі такий самий доступ, який указаний в суперкласі ()

Таким чином, ключ доступа дозволяє перевизначити доступ до елементів сабкласу, що наслідуються від суперкласу. В java = public.

2) Просте наслідування означає, що клас має тільки один суперклас

class QueueWithMax: public queue

{ int max; //за замовчуванням private

public :

QueueWithMax(int Max){max = Max;} //виклик конструктора

//суперкласу за замовчуванням,

//явний виклик конструктора //суперкласу відсутній

QueueWithMax(int Max, int State): queue(State){max = Max;}

//явний виклик конструктора батьківського класу

getMax(); //методи класу

};

QueueWithMax:: QueueWithMax(int Max) //конструктор

{

max = Max;

}

int QueueWithMax:: getMax(){….}

void QueueWithMax:: seize() {….}

Конструктори НЕ наслідуються в С++. Сабклас обов’язково повинен мати свій конструктор. Якщо в описі конструктора відсутній явний виклик конструктора, то викликається конструктор суперкласу за замовчуванням(той, що без параметрів), якщо він є (інакше виникне помилка).

Якщо сабклас має декілька суперкласів, то виклик конструкторів суперкласів здійснюється у тому порядку, у якому вони указані в описі сабкласу.

Для ієрархій класів конструктори викликаються у відповідності до ієрархії, починаючи з верхнього рівня.

Деструктори Не наслідуються. Якщо програміст не визначив деструктора класу-нащадка, то він формується за замовчуванням і викликає деструктори усіх батьківських класів (суперкласів).

Розглянемо механізм виклику методу сабкласу, що перевизначається(метод seize(), наприклад). Якщо змінна в програмі указує на змінну типу сабклас, то викликається метод сабкласу. Але, якщо змінна на початку програми була об’явлена як змінна суперкласу, а потім їй було присвоєне значення змінної типу суперкласу, то при виклику метода Ви з подивом помітите, що викликається метод суперкласу, а не сабкласу.

queue *q; // вказівник на змінну типу суперклас

….

q = new QueueWithMax(2); // тепер вказівник указує на сабклас

....

q ->seize(); //викликається метод, але не сабкласу, а суперкласу

//можна уникнути помилки, якщо використати приведення типів

// (QueueWithMax *q) ->seize();

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

Тому в С++ окрім механізму ранного зв’язування реалізований ще механізм пізнього зв’язування. Механізм пізнього зв’язування означає, що посилання на метод, який викликається, формується на етапі виконання програми в залежності від типу об’єкта, що викликає метод. Механізм пізнього зв’язування реалізований в С++ за допомогою віртуальних методів. визначення віртуального методи здійснюється за допомогою слова virtual („фактичний”, в перекладі з англійської):

virtual void seize(); //опис метода в суперкласі

Отже, якщо метод в суперкласі визначений як віртуальний, то виклик його здійснюється за механізмом пізнього зв’язування, тобто на етапі виконання програми.

queue *q; // вказівник на змінну типу суперклас

….

q = new queue;

….

q ->seize(); // викликається метод суперкласу

….

q = new QueueWithMax(2); // тепер вказівник указує на сабклас

....

q ->seize(); // викликається метод сабкласу,

// оскільки метод був визначений як віртуальний

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

(!)Для кожного об’єкта, що містить хоч один віртуальний метод, компілятор створює таблицю віртуальних методів, що містить адресу метода в пам’яті. Кожний об’єкт містить додаткове скрите поле, що указує на адресу пам’яті об’єкта. На етапі компіляції посилання на віртуальний об’єкт замінюється на звернення до таблиці віртуальних методів через адресу об’єкта. Тому віртуальні методи дещо сповільнюють роботу програми.

(!) В С++ віртуальний механізм працює ТІЛЬКИ при використанні вказівників на об’єкти такі об’єкти називають поліморфними. Поліморфізм полягає в даному випадку в тому, що метод виконується в залежності від об’єкта, який його викликає.

Так само, як і в java, в С++ можна визначити пусті віртуальні методи. Називаються такі методи в С++ чисті віртуальні методи. Для чисто віртуального методи замість тіла функції указується =0:

virtual void getState() =0;

Чисті віртуальні методи обов’язково мають бути перевизначені в сабкласі. Клас, який містить хоч один віртуальний метод називається в С++ абстрактним. Абстракті класи використовуються для визначення загальних понять і використовують для створення сабкласів. Об’єкти абстрактного класу створювати не можна.

Множинне наслідування означає, що сабклас створений на сонві декількох суперкласів. Якщо в суперкласах є елементи з однаковим ім’ям, може виникнути конфлікт ідентифікаторів, запобігти якому можна за допомогою явного указування класу, до якого відноситься метод:

class docent: public Teacher_employee, public Sience_employee

{

….

};

int main()

{

docent Ivanenko;

cout<<Ivanenko. Teacher_employee::getSalary();

cout<<Ivanenko. Sience_employee::getSalary();

return 0;

}

В Java також реалізується механізм раннього та пізнього зв’язування. Називається статичне та динамічне зв’язування. Якщо метод є закритим, статичним або термінальним (private, static, final), то компілятор точно знає, як його викликати. Такий процес називається статичним зв’язуванням. В противному випадку реалізується динамічне зв’язування. Віртуальна Java машина створює таблицю методів (method table) для кожного класу. При виклику методу віртуальна машина переглядає таблицю і знаходить потрібний метод.

(21. Механізм інтерфейсів мови Java.

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