Абстрактные классы

Последнее обновление: 26.09.2025

Кроме обычных классов в Java есть абстрактные классы. Абстрактный класс похож на обычный класс. В абстрактном классе также можно определить поля и методы, но в то же время нельзя создать объект или экземпляр абстрактного класса. Абстрактные классы призваны предоставлять базовый функционал для классов-наследников. А производные классы уже реализуют этот функционал.

При определении абстрактных классов используется ключевое слово abstract:

abstract class имя_класса{

  // содержимое класса
}

Обычно абстрактные классы создаются для таких сущностей, которые представляют лишь абстракцию и в реальности не имеют конкретного воплощения. Хрестоматийным примером является система геометрических фигур. В реальности не существует геометрической фигуры как таковой. Есть круг, прямоугольник, квадрат, но просто фигуры нет. Однако же и круг, и прямоугольник имеют что-то общее и являются фигурами.

Также абстрактные классы могут представлять и, на первый взгляд, конкретные сущности, но объекты которых не будут создаваться в программе и которые должны быть лишь основой для создания классов-наследников.

Например, определим абстрактный класс геометрической фигуры:

abstract class Shape{
    
    int x; // x-координата точки
    int y; // y-координата точки
 
    Shape(int x, int y){
        
        this.x = x;
        this.y = y;
    }

    void print(){ System.out.println("Геометрическая фигура"); }
}

Применение абстрактных классов

Геометрические фигуры, как правило, имеют некоторую точку, относительно которой располагается фигура. Например, для прямоугольника это обычно координаты верхнего левого угла, для круга - это центр и т.д. И в данном случае с помощью полей x и y сохраняем эти координаты, которые передаются через конструктор. А для вывода информации о фигуре предназначен метод print()

Особенностью абстрактных классов является то, что мы не можем использовать их конструктор напрямую для создания объекта класса:

class Program{
      
    public static void main(String[] args) {

        // так нельзя
        Shape someShape = new Shape(10, 15);  // ! Ошибка: Shape is abstract; cannot be instantiated
    }
}

Мы можем вызвать конструктор абстрактного класса лишь в производных классах. Создадим пару производных классов:

// абстрактный класс фигуры
abstract class Shape{
    
    int x; // x-координата точки
    int y; // y-координата точки
 
    Shape(int x, int y){
        
        this.x = x;
        this.y = y;
    }

    void print(){ System.out.println("Геометрическая фигура"); }
}
// производный класс прямоугольника
class Rectangle extends Shape
{
    int width;
    int height;
 
    // конструктор с обращением к конструктору класса Figure
    Rectangle(int x, int y, int width, int height){
        
        super(x,y);

        this.width = width;
        this.height = height;
    }
  
	  @Override
    void print(){ 
        System.out.printf("Пpямоугольник. Верхний левый угол: (%d, %d); Ширина: %d; Длина: %d\n", x, y, width, height);
    }
}
// производный класс круга
class Circle extends Shape
{
    int radius;
 
    // конструктор с обращением к конструктору класса Shape
    Circle(int x, int y, int radius){
        
        super(x,y);
        this.radius = radius;
    }
	
	  @Override
    void print(){ 
        System.out.printf("Круг. Центр: (%d, %d); Радиус: %d\n", x, y, radius);
    }
}

В данном случае определены класс прямоугольника и класс круга. Они наследуют функционал абстрактного класса, добавляя дополнительные поля типа ширины и длины или радиуса, а также переопределяя метод print(). Далее мы можем использовать объекты этих классов как объекты типа Shape:

class Program{
      
    public static void main(String[] args) {

        Shape shape1 = new Rectangle(10, 15, 200, 150);
        Shape shape2 = new Circle(50, 60, 200);

        printShape(shape1);
        printShape(shape2);
    }

    static void printShape(Shape shape){
        shape.print();
    }
}

Консольный вывод:

Пpямоугольник. Верхний левый угол: (10, 15); Ширина: 200; Длина: 150
Круг. Центр: (50, 60); Радиус: 200

Абстрактные методы

Наряду с абстрактными классами в языке Java есть абстрактные методы. Такие методы также предваряются модификатором abstract, но при этом не имеют тела - не выполняют никаких конкретных действий:

abstract тип_метода имя_метода(параметры_метода);

Производный класс обязан переопределить и реализовать все абстрактные методы, которые имеются в базовом абстрактном классе. Также следует учитывать, что если класс имеет хотя бы один абстрактный метод, то данный класс должен быть определен как абстрактный.

Например, в примере с фигурами выше метод print() в классе Shape не выполняет какой-то полезной нагрузки. Производные классы его в любом случае переопределяют, выводя в нем свою информацию. И мы можем сделать его абстрактным:

abstract class Shape{
    
    int x;
    int y;
 
    Shape(int x, int y){
        
        this.x = x;
        this.y = y;
    }
    // абстрактный метод
    abstract void print();
}
// прямоугольник
class Rectangle extends Shape
{
    int width;
    int height;

    Rectangle(int x, int y, int width, int height){
        
        super(x,y);
        this.width = width;
        this.height = height;
    }
	  @Override
    void print(){ 
        System.out.printf("Пpямоугольник. Верхний левый угол: (%d, %d); Ширина: %d; Длина: %d\n", x, y, width, height);
    }
}
// круг
class Circle extends Shape
{
    int radius;
 
    Circle(int x, int y, int radius){
        
        super(x,y);
        this.radius = radius;
    }
	  @Override
    void print(){ 
        System.out.printf("Круг. Центр: (%d, %d); Радиус: %d\n", x, y, radius);
    }
}

Причем производные НЕабстрактные классы обязаны реализовать абстрактный метод.

Другим примером абстрактных методов могут быть такие действия, которые опять же не имеют конкретного воплощения, являются абстракцией и зависят от конкретного класса. Например, у геометрической фигуры можно вычислить периметр и площадь. Но для прямоугольника эти показатели будут вычисляться одним образом, для круга - другим образом и т.д. Для абстрактной геометрической фигуры мы не можем определить универсальный способ вычисления периметра и площади, поэтому такие действия можно определить в виде абстрактных методов. А конкретные классы по своему их реализуют:

abstract class Shape{
    
    int x;
    int y;
 
    Shape(int x, int y){
        
        this.x = x;
        this.y = y;
    }
    // абстрактный метод для вычисления периметра
    abstract double getPerimeter();
    // абстрактный метод для вычисления площади
    abstract double getArea();
}
// прямоугольник
class Rectangle extends Shape
{
    int width;
    int height;

    Rectangle(int x, int y, int width, int height){
        
        super(x,y);
        this.width = width;
        this.height = height;
    }
	@Override
    double getPerimeter(){ return this.width * 2 + this.height * 2; }

	@Override
    double getArea(){ return this.width * this.height; }
}
// круг
class Circle extends Shape
{
    int radius;
 
    Circle(int x, int y, int radius){
        
        super(x,y);
        this.radius = radius;
    }
    
	@Override
    double getPerimeter(){ return this.radius * 3.14 * 2; }

	@Override
    double getArea(){ return this.radius * 3.14; }
}

Применение классов:

class Program{
      
    public static void main(String[] args) {

        Shape shape1 = new Rectangle(10, 15, 200, 150);
        System.out.println("Площадь прямоугольника: " + shape1.getArea());
        System.out.println("Периметер прямоугольника: " + shape1.getPerimeter());

        Shape shape2 = new Circle(50, 60, 100);
        System.out.println("Площадь круга: " + shape2.getArea());
        System.out.println("Периметер круга: " + shape2.getPerimeter());
    }
}

Консольный вывод программы:

Площадь прямоугольника: 30000.0
Периметер прямоугольника: 700.0
Площадь круга: 314.0
Периметер круга: 628.0
Помощь сайту
Юмани:
410011174743222
Номер карты:
4048415020898850
Morty Proxy This is a proxified and sanitized view of the page, visit original site.