JavaRush/Курсы/JAVA 25 SELF/Абстрактные классы и методы: синтаксис, примеры

Абстрактные классы и методы: синтаксис, примеры

Открыта

1. Синтаксис абстрактного класса

Давайте разберёмся, что же такое абстрактный класс в Java и зачем он вообще нужен. Представьте, что у вас есть конструктор LEGO: у вас есть набор деталей (например, «колёса», «кубики»), и есть особые детали для конкретных моделей. Абстрактный класс — это как обобщенная инструкция по обращению с детальками без описания складывания конкретной модели: кубики сцепляются пазами, колёса крепятся к осям, детали можно наращивать слоями. Абстрактный класс описывает именно эти общие правила и обязательные шаги, но не расписывает сборку конкретной модели. Конкретные модели — это подклассы: они берут общую инструкцию и добавляют недостающие шаги.

В Java абстрактный класс — это класс, который не может быть создан напрямую (нельзя сделать new AbstractClass()), но от него можно наследоваться и реализовывать его «недописанные» методы.

Абстрактные классы нужны, когда:

  • У группы объектов есть общее поведение или состояние, но часть логики отличается.
  • Вы хотите реализовать часть функциональности «по умолчанию», а часть оставить на реализацию потомкам.
  • Вы хотите запретить создание объектов этого класса напрямую (например, «Животное» само по себе не встречается, а вот «Кот» — вполне).

Как объявить абстрактный класс

Всё просто: перед словом class пишем ключевое слово abstract.

public abstract class Animal {
    // Поля (например, имя животного)
    protected String name;

    // Конструктор
    public Animal(String name) {
        this.name = name;
    }

    // Абстрактный метод — только объявление, без реализации!
    public abstract void makeSound();

    // Обычный (реализованный) метод
    public void sleep() {
        System.out.println(name + " спит: Zzz...");
    }
}

Особенности:

  • Абстрактный класс может содержать как реализованные методы, так и абстрактные.
  • Абстрактный класс может содержать поля, конструкторы и даже static-методы.
  • Нельзя создать объект абстрактного класса напрямую:
  • Animal a = new Animal("Кто-то"); // Ошибка!

Как объявить абстрактный метод

Абстрактный метод — это метод без тела, то есть без фигурных скобок и кода внутри. Он объявляется с ключевым словом abstract и обязательно заканчивается точкой с запятой ;.

public abstract void makeSound();
  • Абстрактные методы можно объявлять только внутри абстрактного класса.
  • Класс, который наследует абстрактный класс, обязан реализовать все абстрактные методы, иначе он тоже становится abstract.

2. Наследование абстрактных классов: как это работает

Давайте посмотрим на конкретный пример. Пусть у нас есть абстрактный класс Animal с абстрактным методом makeSound(). Теперь создадим класс-наследник Dog, который реализует этот метод:

public class Dog extends Animal {
    public Dog(String name) {
        super(name); // Вызов конструктора базового класса
    }

    @Override
    public void makeSound() {
        System.out.println(name + " лает: Гав-Гав!");
    }
}

И ещё один класс-наследник:

public class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println(name + " мяукает: Мяу!");
    }
}

Теперь мы можем использовать эти классы в программе:

public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog("Шарик");
        Animal cat = new Cat("Мурка");

        dog.makeSound(); // Шарик лает: Гав-Гав!
        cat.makeSound(); // Мурка мяукает: Мяу!

        dog.sleep(); // Шарик спит: Zzz...
        cat.sleep(); // Мурка спит: Zzz...
    }
}

Обратите внимание:
Мы можем объявлять переменные типа Animal, но создавать объекты только конкретных (не абстрактных) потомков.

Схема: как это выглядит

.         Animal (abstract)
            /         \
         Dog         Cat
 (реализует makeSound) (реализует makeSound)

3. Когда использовать абстрактный класс, а когда интерфейс?

Это один из самых популярных вопросов на собеседованиях, и не зря! Давайте разберёмся:

  • Абстрактный класс — когда у объектов есть общее состояние (например, поля), общая логика (методы с реализацией), и вы хотите дать «скелет» поведения с возможностью доработки.
  • Интерфейс — когда вы хотите задать только набор методов (контракт), без реализации и состояния. С Java 8 интерфейсы получили default/static-методы, но всё равно интерфейс — про «что должен уметь объект», а не «как он это делает».

Пример из жизни:
«Птица» — абстрактный класс: у всех птиц есть клюв, крылья, и они могут летать (но по-разному).
«Летающий» — интерфейс: не только птицы умеют летать, но и самолёты, и супергерои! Летают все по-разному, но главное — они это умеют.

4. Практические примеры

Пример 1: Абстрактный класс с частичной реализацией

Допустим, вы делаете игру, где есть разные виды транспорта. Все они могут ехать, но делают это по-разному. Но у всех есть скорость, название и стандартный способ остановки.

public abstract class Transport {
    protected String name;
    protected int speed;

    public Transport(String name, int speed) {
        this.name = name;
        this.speed = speed;
    }

    // Абстрактный метод — реализация в потомках
    public abstract void move();

    // Реализованный метод
    public void stop() {
        System.out.println(name + " остановился.");
    }
}

public class Car extends Transport {
    public Car(String name, int speed) {
        super(name, speed);
    }

    @Override
    public void move() {
        System.out.println(name + " едет по дороге со скоростью " + speed + " км/ч.");
    }
}

public class Bicycle extends Transport {
    public Bicycle(String name, int speed) {
        super(name, speed);
    }

    @Override
    public void move() {
        System.out.println(name + " крутит педали со скоростью " + speed + " км/ч.");
    }
}

Использование:

Transport car = new Car("Toyota", 120);
Transport bike = new Bicycle("Stels", 25);

car.move(); // Toyota едет по дороге со скоростью 120 км/ч.
bike.move(); // Stels крутит педали со скоростью 25 км/ч.

car.stop(); // Toyota остановился.
bike.stop(); // Stels остановился.

Пример 2: Абстрактный метод с параметром

public abstract class Shape {
    public abstract double area();
}

public class Circle extends Shape {
    private double radius;
    public Circle(double radius) {
        this.radius = radius;
    }
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

public class Rectangle extends Shape {
    private double width, height;
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    @Override
    public double area() {
        return width * height;
    }
}

Использование:

Shape c = new Circle(3);
Shape r = new Rectangle(4, 5);

System.out.println("Площадь круга: " + c.area());
System.out.println("Площадь прямоугольника: " + r.area());

5. Особенности и нюансы абстрактных классов

  • Абстрактный класс может содержать любые модификаторы доступа: public, protected, private (например, для полей).
  • Можно объявлять абстрактный класс без абстрактных методов. Это бывает полезно, если вы просто хотите запретить создание экземпляров базового класса.
  • Если класс наследует абстрактный класс, но не реализует все абстрактные методы, он тоже должен быть объявлен как abstract.
  • Абстрактный класс может иметь конструкторы. Они вызываются при создании объекта-наследника (через super(...)).
  • Абстрактные методы не могут быть private (иначе их нельзя будет реализовать в наследнике).
  • Абстрактные классы могут содержать static-методы и поля.
  • Абстрактный класс может реализовывать интерфейсы, но не обязан реализовывать их методы — это могут сделать потомки.

Таблица: сравнение абстрактного класса и интерфейса

Абстрактный класс Интерфейс
Ключевое слово
abstract class
interface
Может содержать поля Да (любые) С Java 8 — только static/final
Методы с реализацией Да С Java 8 — default/static
Абстрактные методы Да Да
Множественное наследование Нет Да (можно реализовать много интерфейсов)
Конструкторы Да Нет
Можно создать объект Нет Нет

6. Типичные ошибки при работе с абстрактными классами и методами

Ошибка №1: попытка создать экземпляр абстрактного класса.
Если вы напишете new Animal("Кто-то"), компилятор сразу же напомнит, что абстрактные классы для этого не предназначены. Помните: абстракция — это «скелет», а не «живой организм».

Ошибка №2: забыли реализовать все абстрактные методы в наследнике.
Если ваш класс не реализует хотя бы один абстрактный метод базового класса, он сам должен быть объявлен как abstract, иначе получите ошибку компиляции.

Ошибка №3: объявили абстрактный метод вне абстрактного класса.
В Java нельзя объявить абстрактный метод в обычном (неабстрактном) классе — компилятор тут же возмутится.

Ошибка №4: попытка сделать абстрактный метод private или static.
Абстрактные методы не могут быть private (иначе их нельзя переопределить) и не могут быть static (потому что статические методы не переопределяются). Ну и final тоже не могут, потому что final запрещает переопределение.

Ошибка №5: забыли про модификатор доступа у абстрактного метода.
Если вы явно не укажете модификатор, метод будет иметь пакетную видимость (package-private), что иногда не то, что вы хотели получить.

1
Задача
JAVA 25 SELF,  19 уровень,  1 лекция
Недоступна
Шифровальная машина: метод с параметром 🔐
Шифровальная машина: метод с параметром 🔐
1
Задача
JAVA 25 SELF,  19 уровень,  1 лекция
Недоступна
Система управления "Умным домом" 📱
Система управления "Умным домом" 📱
1
Задача
JAVA 25 SELF,  19 уровень,  1 лекция
Недоступна
Геометрический редактор: фигуры и их площади 📐
Геометрический редактор: фигуры и их площади 📐
1
Задача
JAVA 25 SELF,  19 уровень,  1 лекция
Недоступна
Кадровая система IT-компании 💼
Кадровая система IT-компании 💼
Комментарии (13)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
nightmarakeshBackend Developer в ITHub
14 июля, 19:13
Задачи повторяются... Если уж пытаться не говорить про их однотипность и с постной миной заниматься одним и тем же в каждом блоке, то когда они еще и одинаковые один в один, эмоция выходят на новый ровень. В предыдущей лекции, которая задача полностью идентична, останавливает от импорта только условия задачи, поэтому пришлось расщедриться на копипаст в этот пакет. Понимаю, что на курс это нен повлияет, скорей просто крик души, который думаю у большинства на этот момент уже появился)
ryzenjava
Уровень 1
13 июля, 20:02
ласт задача просто ахуенная
Матвей Попов
Уровень 20
10 мая, 13:47
Последняя задача прям глоток воздуха, и самому конструкторы сделать надо и реализовать метод возвращаемый имя, прям золото среди однотипных задач муму гавгав мяумяу
Mikryukov Kirill Java Developer
15 июня, 17:22
Это даа
kasnil
Уровень 38
20 января, 17:44
JAVA 25 SELF:
Заменить вызов IO.println на System.out.println или обеспечить существование
класса IO с методом println. В текущем коде используется неизвестный класс IO,
что приведёт к ошибке компиляции, если класса IO нет в проекте.
Kidze
Уровень 38
5 января, 11:41
Муууу! Zzz...
Maks Java Developer
3 декабря 2025, 07:37
может еще 10 лекций будем повторять одно и тоже?
Ksanders
Уровень 32
29 ноября 2025, 10:19
В лекции идет повторение синтаксиса написания абстрактного класса, хотя уже это было на уровне про наследование. А потом сразу сравнение между абстрактным классом и интерфейсом, хотя не объясняется абсолютно что это такое интерфейс и с чем его едят вообще 😕
Anonymous #3356042
Уровень 40
21 октября 2025, 20:06
Задач - проектов действительно не хватает. На тех задачах что даны алгоритмам не научишься
I'll kick them allSenior Task Kicker в JavaTrush
25 сентября 2025, 23:30
А куда делись задачи - проекты? Почему нужно копировать из задачи в задачу код?
Anton Pohodin
Уровень 27
8 октября 2025, 08:01
Последняя задача про кадровую систему содержит неполные требования (касаемо getName()), так что пришлось додумываться самому...
Ksanders
Уровень 32
29 ноября 2025, 11:42
Зато последняя задача хоть немного заставляет задумываться над реализацией (в первые за последние уровни)
Kidze
Уровень 38
5 января, 11:41
Что-то похожее на easy минимальный уровень, да.