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

17. Множинне наслідування та його проблеми.

Множинне наслідування означає можливість мати не один, а декілька суперкласів класу-нащадку. Наприклад, співробітник ВНЗ може бути одночасно і викладачем і науковцем.

Використання множинного наслідування призводить до невизначеності. Наприклад, поле посада в класі викладач і науковець можуть мати різні значення. І якщо викликати метод співробітникВНЗ.getПосада(), то компілятор не зможе розв’язати протиріччя між посиланнями.

Для компілятора реалізація множинного наслідування – велика проблема, тому деякі мови відмовляють програмісту в можливості організації множинного наслідування.

Мови Smalltalk, C#, Objective-C, Object Pascal / Delphi, Java, і PHP не допускають множинного наслідування.

Мова С++ - допускає. В Java замість множинного наслідування введений інструмент множинних інтерфейсів.

18. Реалізація наслідування мовою Java.

1) Для позначення наслідування використовується слово extend:

class queueWithMax extends queue

{

.... ///Додаткові поля та методи класу

}

class queueFIFO extends queue

{

Додаткові поля та методи класу

}

class queueLIFO extends queue

{

Додаткові поля та методи класу

}

class queueWithLeaving extends queue

{

Додаткові поля та методи класу

}

Зауваження: зверніть увагу, що загальні характеристики черги розміщені в суперкласі queue, а спеціальні характеристики розміщуються в сабкласі. Клас smo_simple (дивись попередню лекцію) містить поле типу queue, тобто суперкласу. Усі нащадки цього суперкласу можуть використовуватись там, де використовується суперклас. Наприклад, можливе формування об’єкту smo_simple за допомогою конструктора, в якому передається об’єкт типу queueWithMax (замість типу queue !). Отже, поява черги з новими властивостями не змушує програміста переписувати клас smo_simple (!).

2) Поля і методи сабкласу НЕ мають прямого доступу до полів та методів суперкласу. Доступ до методів суперкласу з сабкласу здійснюється за допомагою слова super. А доступ до полів суперкласу з сабкласу здійснюється тільки за домогою методів доступу (get, і тільки якщо він написаний програмістом). Слово super означає виклик методу батьківського класу (суперкласу).

class queueWithMax extends queue

{

...

public void seize()

{

if(super.getState()<max)

super.seize;

}

}

3) Побудова конструктора класа-нащадка має починатись зі звернення до конструктора суперкласу (у першому рядочку конструктора!):

class queueWithMax extends queue

{ …

public queueWithMax(int State, int Max)

{

super(State);

max = Max;

}

Зауваження: якщо в сабкласі не має явного виклику конструктора суперкласу, то викликається конструктор за замовчування (той, що не має параметрів). якщо є в суперкласі такий конструктор не описаний, то компілятор генерує помилку.

4) Методи сабкласу, що переписуються (перевизначаються) відмічаються компілятором середовища NteBean словом @Override, що в перкладі значить перевизначення.

5) В мові Java тип об’єктної змінної визначає множину типів, на які може посилатись змінна. Наприклад, масив об’єктів типу Teacher може складатись з об’єктів, які належать до сабкласів класу Teacher:

Professor Ivanenko = new Professor(“Іваненко Сергій Петрович”, …); //

Teacher[ ] kafedra= new Teacher[10];

Teacher[0] = Ivanenko //Тепер змінна Teacher[0] посилається

// на об’єкт класу Professor

Teacher[1] = new Teacher(…..); //

Teacher[10] = new Teacher(…..); //

6) Для деяких класів поява класів-нащадків є не бажаною. Тому в мові Java передбачена заборона появи класів-нащадків за допомогою слова final:

final class queueWithMax extends queue

{

….

}

Такий клас називається термінальним. Наприклад, в мові Java клас String є термінальним. Це забезпечує, що ніхто не може переписати цей тип об’єктної змінної.

Окремий метод класу також можна позначити словом final. Це буде означати, що такий метод не можна перевизначити в класі-нащадку:

class queueWithMax extends queue

{

….

public final void seize()

{…}

}

Такий метод називається термінальним. Наприклад, в класі Calendar методи getTme() і setTime() являються термінальними. Це забезпечує, що змінити формат виводу дати неможливо.

Зауваження: усі методи термінального класу являються термінальними.

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

if(q instanceof queueWithMax) …;

Але якщо в програмі є необхідність використання цього оператора, подумайте, можливо, Ваша програма неправильно побудована. В рамках тестування - дуже зручно і корисно.

8) Існує можливість перетворення об’єкта типу суперклас в об’єкт типу сабклас:

Professor boss = (Professor)Teacner[0]; // помилки не має, оскільки змінна

// Teacner[0] посилається на змінну

// типу Professor

Professor boss = (Professor)Teacner[1]; // є помилка (!), оскільки змінна

// Teacner[1] посилається на змінну

// типу Teacher

Щоб уникнути такої помилки можна скористатись оператором instanceof:

if(Teacner[1] instanceof Professor)

Professor boss = (Professor)Teacner[1];

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

Professor boss = (Student)Teacner[1]; // є помилка (!), оскільки тип Student

// являється сабкласом класу Teach

9) На верхньому рівні ієрархії інколи класи набувають настільки абстрактного вигляду, що екземпляри цього класу не мають змісту і не створюються в процесі виконання програми. Клас, об’єкти якого не створюються, називається абстрактним. Абстрактний клас має наступний опис:

abstract class Person

{

поля і методи класу //Конструктора не має!

}

Зауваження: створити об’єкти абстрактного класу неможливо.

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

class Person

{

public abstract String getName(); //Опису методу не має!

}

10) Для обмеження доступу до поля чи методу класу інших класів, окрім підкласів (класів-нащадків, сабкласів), використовують слово protected (захищений). Не бажано використовувати protected поля. проте бажано і корисно використовувати protected методи. Метод класу, який об’явлений як protected можуть використовувати тільки об’єкти, які належать до сабкласів цього класу. Використання методу об’єктами інших класів (які не являються нащадками класу) не дозволено.

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

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