Використання успадкування класів у Java
Існують два види успадкування класів в Java - конкретизація (звуження) та розширення. При конкретизації загальний клас уточнюється у приватних підкласах. Ці підкласи по відношенню до суперкласу є «примірником» і успадковують усі методи суперкласу. Якщо метод виконується коректно у підкласі, жодних подальших змін не потрібно. З іншого боку, якщо в підкласі метод суперкласу не працює, то в цьому підкласі цей метод слід перевизначити, щоб він міг виконувати необхідні в цьому класі операції. Наприклад, є загальний клас Dog, який містить метод drink та метод sniff. При конкретизації цього класу в класі Bloodhound метод drink не вимагатиме змін, тому що всі собаки лакають однаковим чином. Однак, ймовірно, знадобиться перевизначення методу sniff, оскільки собака породи бладхаунд має набагато розвиненіший нюх, ніж «узагальнений» собака. В даному випадку клас Bloodhound конкретизує метод суперкласу Dog.
При використанні розширення завдяки успадкування класів багаторазово використовуються ділянки коду з описом методів суперкласу, після чого до підкласів додаються нові методи, розширюючи таким чином функціональні можливості класу. Наприклад, у тому ж класі Dog можна створити підклас BorderCollie, який успадковує всі загальні методи класу Dog, після чого в ньому додатково описується метод herd, так як собаки породи коллі мають пастуший інстинкт, не властивий іншим собакам. Додавання нового методу розширюються функціональні можливості загального класу.
Спадкування класів у Java
У Java кожен клас може розширити лише один клас. Якщо навіть в описі класу відсутній явний оператор extends, цей клас успадковує лише один клас, який у цьому випадку єкласом java.lang.Object. У зв'язку з цією особливістю кажуть, що Java допускається лише одиничне успадкування класів.
Типи перевизначення методів
При уточненні ж новий метод не замінює метод суперкласу, а натомість метод суперкласу дописується додатковий код.
У Java всі методи конструктора використовують уточнення при перевизначенні методів за схемою зчеплення конструкторів. Зокрема виконання конструктора починається зі звернення до конструктора суперкласу, яке може бути явним або неявним. Для явного звернення до конструктора використовується оператор super, який свідчить про виклик суперкласу (наприклад, super() викликає конструктор суперкласу без аргументів). Якщо ж у тілі конструктора явне поводження відсутня, компілятор автоматично поміщає у першому рядку конструктора звернення до методу super(). Тобто у мові Java у конструкторах використовується уточнення при перевизначенні методів, а звичайних методах використовується заміщення.
Ключове слово this
Іноді в класі Java необхідно звернутися до поточного екземпляра даного класу, який в даний момент обробляється методом. Для такого звернення використовується це ключове слово. Застосування цієї конструкції зручне у разі потреби звернення до поля поточного об'єкта, ім'я якого збігається з ім'ям змінної, описаної в цьому блоці, як показано в наступній програмі:
public class ThisTester
// Змінна екземпляра класу: public int dog = 2;
this.dog = (int) dog; // дві різні змінні dog! >
System.out.printlnC'After clobbering, dog = "+ t.dog);
Після виконання програми виводиться така інформація:
The dog field = 2
After clobbering, dog = 5
Приклад успадкуваннякласів у Java
Щоб більш конкретно вивчити поняття успадкування і поліморфізму в Java, розглянемо кілька простих прикладів.
Зокрема, розглянемо кілька прикладів класів, у яких створюються та виводяться числові прогресії. Числова прогресія — це послідовність значень, причому значення кожного елемента прогресії залежить від однієї чи більше попередніх членів. Наприклад, в арифметичній прогресії значення наступного члена прогресії визначається шляхом додавання, а в геометричній прогресії - шляхом множення. У будь-якому випадку у прогресії повинен існувати спосіб визначення першого члена прогресії, а також спосіб визначення значення поточного прогресу члена.
Почнемо з опису класу Progression, показаного фрагментом коду 2.1. У цьому класі описані «загальні» поля та методи числової прогресії. Зокрема, цей клас описує такі два поля типу long-integer:
• first: значення першого члена прогресії;
• cur: значення поточного члена прогресії;
а також наступні три методи:
firstValue(): визначає перший член професії та повертає його значення.
Input: ні; Output: ціле число типу \or\g.
nextValue(): переходить до наступного члена прогресії та повертає його значення. Input: ні; Output: ціле число типу long.
printProgression(n): обчислює прогресію і виводить значення перших членів прогресії. Input: ціле число; Output: ні.
Говорячи, що метод printprogression не має вихідних даних, мають на увазі, що він не повертає ніякого значення, в той час як методи першоївалу та nextvalue повертають значення типу long-integer. Таким чином, firstValue і nextValue є функціями, а printProgression - процедурою.
Клас Progression такожмістить метод Progression(), котрий є конструктором. Такі методи-конструктори задають початкові значення змінних екземпляра класу під час створення нового об'єкта даного класу. Клас Progression є загальним суперкласом, який успадковують нижчі класи. Таким чином, зазначений конструктор є кодом, який буде включений до кодів усіх класів, що розширюють клас Progression.
*Клас числових прогресій.
public class Progression
/** Значення першого члена прогресії. 7 protected long first;
Г * значення поточного члена прогресії. 7 protected long cur;
Г* стандартний конструктор 7 Progression() < cur = first = 0;
Г* визначає перший член прогресії. *
* Повертає значення першого члена прогресії
/** Прогресія переходить до наступного значення.
* Повертає значення наступного члена прогресії
protected long nextValue()
return ++cur; // наступне значення за замовчуванням >
Г * друкує значення перших членів прогресії.
'параметр п - число членів прогресії, що виводяться на друк.
public void printProgression(int n) < System.out.print(firstValue()); for (int i = 2; i 40 >2 63 , геометрична прогресія зі знаменником 3 вийде за межі довгих цілих чисел після 40 повторень. Крім того, значення 94-го члена прогресії Фібоначчі більше 2 63 , що призведе до переповнення після 94 повторень Ще одна проблема полягає в тому, що неможливо довільно задати початкові значення прогресії Фібоначчі.Наприклад, чи можна задати ці початкові значення рівними 0 і -1?Необхідне використання певного механізму управління та запобігання можливості введення невірних даних або виникнення помилок, які можуть проявитися вході виконання Java-програми. Ці теми будуть розглянуті далі.
Г* Програма тестування класів прогресії 7 class Tester
System.out.printlnf Arithmetic progression with default increment: prog = new ArithProgression(); prog.printProgression(10);
System, out. printlnf Arithmetic progression with increment 5:"); prog = new ArithProgression(5); prog.printProgression(10); // перевіряє GeomProgression
System.out.printlnfGeometnc progression with default base:"); prog = new GeomProgression(); prog.printProgression(10);
System.out. printlnfGeometric progression with base 3:"); prog = new GeomProgression(3); prog.printProgression(10); // перевіряє FibonacciProgression
System.out. printlnfFibonacci progression with default start values:"); prog = new FibonacciProgressionQ; prog.printProgression(IO);
System, out. printlnfFibonacci progression with start values 4 and 6:"); prog = new FibonacciProgression(4,6);
Фрагмент коду 2.5. Програма тестування класів прогресії
Arithmetic progression with default increment (Арифметична прогресія із заданим за замовчуванням значенням різниці): 0123456789 Arithmetic progression with inctement 5 (Арифметична прогресія зі значенням різниці 5): 0 5 10 15 20 25 30 3е заданим за замовчуванням значенням знаменника): 2 4 8 16 32 64 128 256 512 1024 Geometric progression with base 3 (Геометрична прогресія зі значенням знаменника 3): 3 start values (Прогресія Фібоначчі із заданими за замовчуванням першими значеннями): 0 1 1 2 3 5 8 13 21 34 Fibonacci progression with start values 4 and 6 (Прогресія Фібоначчі зпочатковими значеннями 4 і 6): 4 6 10 16 26 42 68 110 178 288
Фрагмент коду 2.6. Результат виконання програми Tester, поданої фрагментом коду 2.5