JavaRush /Курсы /Java Syntax Pro /Абстрактные классы

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

Java Syntax Pro
18 уровень , 6 лекция
Открыта

1. Общий базовый класс

Сегодня просто день интересных тем. Помните ситуацию, когда мы ввели базовый класс ChessItem для упрощения всех классов шахматных фигур? Надеюсь, что да 🙂

Теперь представьте, что у каждой фигуры есть метод, который занимается ее отрисовкой на экране, например, draw(). Вызываешь метод draw(), и фигура сама себя рисует в своих текущих координатах. Удобно было бы вынести этот метод в базовый класс.

Если бы метод draw() был у базового класса ChessItem, можно было бы переопределить его в классах фигур и писать такой элегантный код:

class ChessBoard
{
   public void drawAllChessItems()
   {
      // добавляем фигуры в список
      ArrayList<ChessItem> items = new ArrayList<ChessItem>();
      items.add(new King());
      items.add(new Queen());
      items.add(new Bishop());

      // рисуем их независимо от типа
      for(ChessItem item: items)
 {          item.draw();
      }
   }
}

Введение базового класса ChessItem помогает очень упростить код: не нужно вызывать методы каждого класса отдельно, можно легко хранить все объекты в одной коллекции и т.п.

Зато есть один интересный вопрос: а что должен отрисовывать на экране метод draw(), объявленный непосредственно в самом классе ChessItem? Ведь такой фигуры в шахматах нет, значит и рисовать нечего.

Именно. Более того, создавать объекты типа ChessItem не имеет смысла. Это не фигура из шахмат, а всего лишь абстракция — класс, который мы сделали для удобства. Так работает абстракция из ООП: мы вынесли важные (общие для всех фигур) данные и методы в базовый класс, а их различия оставили в их классах.


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

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

Для такого случая в Java есть специальный тип классов — абстрактные классы. Они созданы для того, чтобы программисты могли упростить работу с похожими классами и уменьшить количество похожего кода в них.

Вот три вещи, которые стоит знать об абстрактных классах.

Метод без реализации

Абстрактный класс может содержать объявление метода без его реализации. Такой метод называется абстрактным. Вместо тела метода просто ставится точка с запятой. А перед названием метода пишется ключевое слово — abstract. Пример:

public abstract class ChessItem
{
   public int x, y; // координаты
   private int value; // «ценность» фигуры
   public int getValue() // обычный метод, возвращает значение value
   {
      return value;
   }

   public abstract void draw(); // абстрактный метод. Реализация отсутствует.
}

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

Каждый метод без реализации помечается специальным ключевым словом abstract. Если в классе есть хоть один абстрактный метод, класс тоже помечается ключевым словом abstract.

Запрет на создание объектов

Создавать объекты абстрактного класса нельзя. Такой код просто не скомпилируется.

Код Описание
ChessItem item = new ChessItem();
item.draw();
Этот код не скомпилируется
ChessItem item = new Queen();
item.draw();
А так можно

Наследование от абстрактного класса

Если вы наследовали свой класс от абстрактного класса, нужно переопределить все унаследованные абстрактные методы — написать для них реализацию. Иначе такой класс тоже придется объявить абстрактным.

Если в классе есть хотя бы один нереализованный метод, объявленный прямо в нем или унаследованный от класса-родителя, класс считается абстрактным.

И зачем это все нужно? Зачем нужны абстрактные классы? Разве нельзя вместо них использовать обычные? А вместо абстрактных методов просто писать две скобочки в качестве тела метода – {}?

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

То же и с абстрактным классом. Тот, кто написал этот класс, не хочет, чтобы создавались его объекты. Наоборот, он рассчитывает на то, что от его абстрактного класса будут наследоваться и переопределяться абстрактные методы.

Преимущество этого подхода проявляется в больших проектах. Чем больше классов, тем чётче приходится очерчивать их роли. Вы увидите преимущество этого подхода, и уже в ближайшем будущем. Все через это проходят.


18
Задача
Java Syntax Pro, 18 уровень, 6 лекция
Недоступна
Абстрактные фигуры
Класс Shape обозначает геометрическую фигуру. В будущем от него можно будет унаследовать какую-то конкретную фигуру. У этой фигуры можно будет посчитать периметр и площадь. У разных фигур они считаются по разным формулам. И так как ни периметр, ни площадь невозможно высчитать у абстрактной фигуры, к
18
Задача
Java Syntax Pro, 18 уровень, 6 лекция
Недоступна
От абстракции к реальности
Класс Person объявлен как абстрактный. Это значит, что мы не можем создавать его экземпляры. Сделай из данного класса обычный, допиши недостающую логику, которая отвечает общепринятым подходам к инкапсуляции: геттеры должны возвращать, а сеттеры — устанавливать значения соответствующим полям.
Комментарии (164)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Юрий Уровень 20
27 февраля 2025
А ты зачем учишь java?
Agent_Pandora Уровень 25
5 апреля 2025
Frontend Developer
26 апреля 2025
Смена сферы деятельности. Новое направление в жизни, которым я могу заниматься с энтузиазмом без мотивации, без подталкивания. Мне это действительно интересно
Aleksei Уровень 19
18 февраля 2025
Лучше ролик Алишева на эту тему посмотреть - гораздо понятнее чем в лекции.
Cryptosin Уровень 21
14 февраля 2025
Абстрактный класс в Java — это класс, который не может быть напрямую создан (то есть нельзя создать его экземпляр), и его основное назначение — служить базой для других классов. Он может содержать как абстрактные методы, так и обычные (реализованные). Абстрактные методы — это методы, которые не имеют реализации в самом абстрактном классе, и обязаны быть реализованы в его подклассах. Основные особенности абстрактных классов: 1 - Невозможность создания экземпляра: Нельзя создать объект абстрактного класса напрямую. Например:

abstract class Animal {
    abstract void sound();
}
// Ошибка:
// Animal a = new Animal();  // Невозможно создать экземпляр абстрактного класса
2 - Абстрактные методы: Это методы, которые не имеют тела в абстрактном классе, и они должны быть реализованы в его подклассах.

abstract class Animal {
    abstract void makeSound();  // абстрактный метод
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Woof");
    }
}
3 - Обычные методы: Абстрактный класс может содержать обычные методы с реализацией, которые могут быть использованы подклассами.

abstract class Animal {
    void sleep() {
        System.out.println("Sleeping");
    }
}
4 - Конструкторы: Абстрактные классы могут иметь конструкторы, но их можно вызывать только через подклассы.

abstract class Animal {
    Animal() {
        System.out.println("Animal is created");
    }
}

class Dog extends Animal {
    Dog() {
        super();  // Вызов конструктора родительского класса
    }
}
5 - Модификаторы доступа: Абстрактные методы могут иметь различные модификаторы доступа (например, public, protected, или private). Однако, они должны быть реализованы в подклассах с таким же или более широким доступом.
Cryptosin Уровень 21
14 февраля 2025
6 - Наследование: Абстрактный класс может наследоваться от другого абстрактного класса, и тогда абстрактные методы родительского класса должны быть реализованы в дочернем классе.

abstract class Animal {
    abstract void sound();
}

abstract class Mammal extends Animal {
    // Не реализуется метод sound, потому что Mammal тоже абстрактный
}

class Dog extends Mammal {
    @Override
    void sound() {
        System.out.println("Bark");
    }
}
7 - Абстрактные классы vs Интерфейсы: Главное отличие абстрактных классов от интерфейсов в том, что абстрактные классы могут содержать реализацию методов, а интерфейсы — нет (до Java 8, но после этого интерфейсы могут содержать дефолтные методы с реализацией). Абстрактные классы могут также содержать поля, которые могут быть инициализированы, тогда как интерфейсы — только константы (поля static final).

abstract class Vehicle {
    abstract void start();  // абстрактный метод

    void stop() {  // обычный метод
        System.out.println("Vehicle stopped");
    }
}

class Car extends Vehicle {
    @Override
    void start() {
        System.out.println("Car started");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle vehicle = new Car();
        vehicle.start();  // "Car started"
        vehicle.stop();   // "Vehicle stopped"
    }
}
Нюансы: - Абстрактные классы могут использоваться для создания общих интерфейсов для групп классов, которые имеют общие характеристики. - Если абстрактный класс наследуется от другого абстрактного класса, то дочерний класс обязан реализовать все абстрактные методы, если только он сам не объявлен абстрактным. - Абстрактные классы могут быть полезны, когда нужно предоставить частичную реализацию с некоторыми абстрактными методами, которые будут различаться в дочерних классах.
Victor Уровень 29
11 февраля 2025
Вот такой main написал для проверки последней задачи "От абстракции к реальности": public class Solution { public static void main(String[] args) { Person maSha = new Person(); maSha.setName("Маша Рыбкина"); maSha.setAge(32); System.out.println("Девочка " + maSha.getName() + ", возраст " + maSha.getAge() + " года."); } }
Vitalii Shevchenko Уровень 29
12 марта 2025
Якщо є бажання допомогти, то можна дать підказку, а не дать списать
Lizzka Уровень 24
31 января 2025
"Помните ситуацию, когда мы ввели базовый класс ChessItem для упрощения всех классов шахматных фигур?" - мне кажется или не было такого? Или я что-то путаю...?
Матвей Шавлов Уровень 25
1 февраля 2025
было, там где первое знакомство с ООП и про принцип слабой связоности
Kidze Уровень 22
3 февраля 2025
было конечно, но пришлось искать вручную, ссылка бы не помешала в лекции для удобства
Hofman Hagl Уровень 26
15 декабря 2024
Не понятно, что значит - "если вы унаследовали свой абстрактный класс...", если класс объявлен абстрактным, ты не можешь его не унаследовать...
Anonymous #3513637 Уровень 25
27 декабря 2024
не унаследовали свой абстрактный класс, а наследовали свой класс от абстрактного
Hofman Hagl Уровень 26
27 декабря 2024
Сути вообще не меняет.
ВК Уровень 36
4 декабря 2024
Темы для быстрой прокачки.
Roman Mayorov Уровень 38
22 ноября 2024
Тема топ, примеры топ, топаем на следующую лекцию 😁
Rustam Уровень 26 Student
17 октября 2024
Очень хорошее объяснение. Примеры сильно помогают
Sergei R. Уровень 26
9 октября 2024
Напомнило фразу из фильма "Игрок": - Ты пьёшь? Можно пить и пить. Я - пью.