Назад Зміст Вперед

8.1. Абстрактні класи

Абстрактні класи

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

abstract class Vidvolikluj {
// оголошення абстрактного класу 
... 
...
// Vidvolikluj obj = new Vidvolikluj(); помилка, неможливо створити об’єкт для абстрактного класу ...

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

abstract class Vidvolikluj { 
// оголошення абстрактного класу 
... 
abstract void vuvid(); 
// оголошення абстрактного метода 
}

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

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

Програма AbstraktKlas.java показує використання абстрактного класу:
package klas;
abstract class ArufmOperacija { 
/* створюється абстрактний клас, який містить дві змінні, над якими будуть здійснюватися арифметичні операції, та абстрактний метод vuvid(), який буде реалізовуватися для кожного підкласу окремо */
  int quslo1;
  int quslo2;
  
  ArufmOperacija(int x, int y) {
    quslo1 = x;
    quslo2 = y;
  }
  
  abstract void vuvid(); 
/* абстрактний клас vuvid() має перевизначатися для кожного   підкласу. Це шаблон методу виведення в консоль результату здійснення   арифметичної операції. В залежності від підкласу, до якого належатиме перевизначена   версія методу, буде здійснюватися відповідна арифметична операція */
}

class Dodavannja extends ArufmOperacija {
  Dodavannja(int x, int y) {
    super(x, y); 
/* через конструктор суперкласу ініціалізуються успадковані поля quslo1 та quslo2 */
  }
  
  void vuvid() { 
/* перевизначення абстрактного методу vuvid(), виводить у консоль результат додавання значень полів quslo1 та quslo2 */
    System.out.println("Додавання першого та другого числа дорівнює" + 
      (quslo1 + quslo2));
  }
}

class Vidnimannja extends ArufmOperacija {
  Vidnimannja(int x, int y) {
    super(x, y);
  }
  
  void vuvid() {
/* перевизначення абстрактного методу vuvid(), виводить у консоль   результат віднімання значення поля quslo2 від значення поля quslo1 */
    System.out.println("Віднімання від першого числа другого числа дорівнює"  + 
      (quslo1 - quslo2));
  }
}

class Mnogennja extends ArufmOperacija {
  Mnogennja(int x, int y) { 
/* перевизначення абстрактного методу vuvid(),   виводить у консоль результат множення значень полів quslo1 та quslo2 */
    super(x, y);
  }
  
  void vuvid() {
    System.out.println("Множення першого числа на друге дорівнює"  + 
      (quslo1 * quslo2));
  }
}

class Dilennja extends ArufmOperacija {
  Dilennja(int x, int y) { 
/* перевизначення абстрактного методу vuvid(), виводить у консоль результат ділення значення поля quslo1 на значення поля quslo2 */
    super(x, y);
  }
  
  void vuvid() {
    if(quslo2 == 0) { // якщо дільник дорівнює нулю
      System.out.println("На нуль ділити не можна!");
      return; // припиняється виконання методу
    }
    System.out.println("Ділення першого числа на друге дорівнює"  + 
      (quslo1 / quslo2));
  }
}
public class AbstraktKlas {
  public static void main(String args[]) {
    ArufmOperacija aOp; 
/* об’єкт для абстрактного класу створювати не можна, але можна створити об'єктну змінну(посилання) */

// Створення об’єктів підкласів класу ArufmOperacija
    Dodavannja dod = new Dodavannja(3, 8);
    Vidnimannja vidn = new Vidnimannja(10, -17);
    Mnogennja mnog = new Mnogennja(5, 19);
    Dilennja dil = new Dilennja(6, 0);
    
    aOp = dod; // змінна aOp посилається на об’єкт класу Dodavannja
    aOp.vuvid(); // виконання перевизначеного методу vuvid() класу Dodavannja
    
    aOp = vidn; // змінна aOp посилається на об’єкт класу Vidnimannja
    aOp.vuvid(); // виконання перевизначеного методу vuvid() класу Vidnimannja
    
    aOp = mnog; // змінна aOp посилається на об’єкт класу Mnogennja
    aOp.vuvid(); // виконання перевизначеного методу vuvid() класу Mnogennja
    
    aOp = dil; // змінна aOp посилається на об’єкт класу Dilennja
    aOp.vuvid(); // виконання перевизначеного методу vuvid() класу Dilennja
  }
}

Результат:
Додавання першого та другого числа дорівнює 11
Віднімання від першого числа другого числа дорівнює27
Множення першого числа на друге дорівнює 95
На нуль ділити не можна!

В цій програмі абстрактний клас ArufmOperacija є взірцем для створення підкласів, які призначатимуться для виконання конкретних арифметичних операцій. Абстрактний метод vuvid() перевантажується в кожному підкласі, де він виводить у консоль результат виконання конкретної арифметичної операції в залежності від класу: в класі Dodavannja — результат додавання, в класі Dilennja — результат ділення... Хоча абстрактний клас ArufmOperacija не може створювати об’єктів, він може створювати змінні, які будуть посилатися на об’єкти його підкласів. В залежності від типу об’єкту, на який посилається змінна aOp класу ArufmOperacija, буде виконуватися відповідне перевизначення методуvuvid() підкласу, до якого належить цей об’єкт. Якщо хоча б в одному підкласі не перевизначатиметься метод vuvid(), програма повідомить про помилку.


1) Абстрактний клас може містити оголошення методу без його реалізації. Такий метод називається абстрактним.

Наприклад:
public abstract class ChessItem
{
 public int x, y; //координати
 private int value; // «цінність» фігури

 public int getValue() //звичайний метод, який повертає значення value
 {
   return value;
 }
 public abstract void draw(); //абстрактний метод. Реалізація відсутня.

}

2) Абстрактний метод позначається спеціальним ключовим словом abstract.

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

3) Створювати об'єкти абстрактного класу не можна. Такий код просто не скомпілюється.

Цей код не скомпілюється:
ChessItem item = new ChessItem();
item.draw();

А такий скомпілюється:ChessItem item = new Queen();
item.draw();

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