🔥 🚀 Важно для всех, кто работает с Java! 🔥
На JavaRocks ты найдешь уникальные туториалы, практические задачи и редкие книги, которых не найти в свободном доступе. Присоединяйся к нашему Telegram-каналу JavaRocks — стань частью профессионального сообщества!
В этой статье разберемся с абстракциями в Java. Вы можете выбрать удобный для вас формат — посмотреть видеоурок на английском языке, либо же прочитать подробный текстовый разбор ниже.
Если вы только начинаете разбираться в Java, то, скорее всего, уже встречали такое понятие, как “абстракция”. Звучит сложно, но не стоит переживать — всё куда проще, чем кажется. Абстракция — это просто способ упростить вещи, не вникая в реализацию. Например, управляя рулем автомобиля, вы же не думаете каждый раз, как работает двигатель. Разберемся с абстракцией — и всё встанет на свои места.
Что такое абстракция в Java?
Допустим, вы пользуетесь пультом от телевизора. Вы нажимаете кнопку, и он работает. Вас интересуют провода и схемы внутри? Нет! Это и есть абстракция — все мелкие детали скрыты, взаимодействие осуществляется только с нужным интерфейсом.
В Java тот же принцип: показано что делает объект, но скрыто как он это делает. Это делает код чище и упрощает его поддержку.
Абстрактные методы — мощный инструмент в Java, который расширяет возможности ООП, особенно в плане полиморфизма. С их помощью можно задать основу логики, оставив детали реализации подклассам.
Что такое абстрактный метод?
Абстрактный метод — это метод без реализации. У него есть только объявление: имя, тип возвращаемого значения и список параметров. Пример:
public abstract int example(int a1, int a2);
Из этой записи понятно, что метод возвращает значение типа int
и принимает два параметра того же типа. А вот как реализован этот метод, сказать нельзя. Чтобы метод заработал, его нужно переопределить.
Создавая абстрактный метод в Java, необходимо соблюдать определенные правила, иначе программа не скомпилируется.
Обратите внимание:
- Абстрактные методы Java не имеют реализации. Он не должен содержать тело метода (то есть фигурные скобки и код внутри). Объявление просто заканчивается точкой с запятой.
- Абстрактные методы могут находиться только в абстрактных классах. Объявлять абстрактные методы в конкретных классах запрещено.
Важно: абстрактный класс может содержать конструкторы и при этом не обязан иметь абстрактные методы. - Если конкретный класс наследуется от абстрактного, он обязан реализовать все его абстрактные методы. В противном случае его тоже придётся объявить как
abstract
.
Последние два пункта могут звучать запутанно, поэтому давайте остановимся на них подробнее.
Наследование абстрактных классов в Java
Допустим, мы хотим написать программу, которая будет рассчитывать периметр и площадь геометрических фигур. Для начала создадим абстрактный родительский класс. Так как для каждой фигуры своя формула, вычисления будут разными. Поэтому пишем абстрактный класс Shape
следующим образом:
abstract class Shape {
String shapeName = " ";
Shape(String name) {
this.shapeName = name;
}
abstract double area();
abstract double perimeter();
}
Run CodeТеперь, чтобы использовать абстрактные методы, нужно унаследовать абстрактный класс Shape
и реализовать недостающие методы. То есть каждый конкретный подкласс обязан прописать свою реализацию area()
и perimeter()
. Например:
class Quadrilateral extends Shape
{
double length, width;
Quadrilateral(double l, double w, String name)
{
super(name);
this.length = l;
this.width = w;
}
@Override
public double perimeter()
{
return ((2*length)+(2*width));
}
@Override
public double area()
{
return (length*width);
}
}
Run CodeА вот как использовать этот класс в main
:
class Main
{
public static void main (String[] args)
{
// creating a Quadrilateral object using Shape as reference
Shape rectangle = new Quadrilateral(3,4, "Rectangle");
System.out.println("Area of rectangle is " + rectangle.area());
System.out.println("Perimeter of rectangle is " + rectangle.perimeter());
}
}
Run CodeВывод в консоли будет выглядеть следующим образом:
Area of rectangle is 12.0
Perimeter of rectangle is 14.0
Важно: Quadrilateral
не обязан реализовывать конструктор Shape(String name)
, потому что это не абстрактный метод — просто обычный конструктор.
А вот если бы было реализовано только area()
или только perimeter()
, то класс Quadrilateral
пришлось бы тоже объявить как abstract
, иначе компилятор не пропустит.
Кстати, абстрактные методы можно использовать не только в абстрактных классах, но и в интерфейсах.
Абстрактные методы в интерфейсах Java
Вспомним, что такое интерфейс и чем он отличается от абстрактного класса.
В интерфейсе все переменные по умолчанию являются public static final
. А вот в абстрактных классах переменные могут быть любыми, но не final
. Методы интерфейса по умолчанию public
, а в абстрактных классах можно использовать различные модификаторы доступа. И главное: класс не наследует интерфейс, а реализует его с помощью implements
.
До выхода Java 8 интерфейсы могли содержать только абстрактные методы. Теперь интерфейс может иметь стандартные default
и статические static
методы. И сейчас чаще используют интерфейсы как шаблоны для наследования, а не абстрактные классы.
Если бы мы создали Shape
интерфейсом, а Quadrilateral
— классом, который его реализует, то пришлось бы отказаться от конструктора Shape(String name)
, потому что в интерфейсах нет конструкторов. Интерфейс выглядел бы вот так:
interface Shape {
abstract double area();
abstract double perimeter();
}
Run CodeА класс Quadrilateral
, реализующий этот интерфейс, будет выглядеть так:
class Quadrilateral implements Shape {
double length, width;
Quadrilateral(double l, double w) {
this.length = l;
this.width = w;
}
@Override
public double perimeter() {
return ((2*length)+(2*width));
}
@Override
public double area() {
return (length*width);
}
}
Run CodeИспользование класса — практически такое же:
class Main
{
public static void main (String[] args)
{
// creating a Quadrilateral object using Shape as reference
Shape rectangle = new Quadrilateral(3,4);
System.out.println("Area of rectangle is " + rectangle.area());
System.out.println("Perimeter of rectangle is " + rectangle.perimeter());
}
}
Run CodeИ получим такой вывод в консоли:
Area of rectangle is 12.0
Perimeter of rectangle is 14.0
Зачем использовать абстрактные методы в Java?
Существует множество причин, по которым абстрактные методы в Java используются и почему важно научиться с ними работать. Вот три основные причины, по которым стоит их использовать, когда это уместно:
- Предотвращение дублирования. Вспомните пример с геометрическими фигурами. А теперь представьте, что вам и вашей команде нужно создать еще классы для других фигур. Сколько вариантов реализации можно придумать? Десять? Пятнадцать? И это еще простая задача. Представьте себе что-то гораздо более сложное — вариантов решения может быть сотни. Это затруднит объединение всего кода в одну систему. Абстрактные методы помогают задать единый шаблон и избежать разрозненности.
- Определенность в реализации. Используя абстрактные методы в интерфейсах и абстрактных классах, вы определяете, как другие разработчики будут взаимодействовать с вашим кодом. Вы задаете названия и сигнатуры методов, указываете, какие данные ожидаются на входе и что будет возвращено. Даже если реализация будет отличаться, интерфейс останется единым. Если кто-то захочет реализовать
Shape
, то ему придется прописатьarea()
иperimeter()
. - Читаемость и отладка. Абстрактные методы делают код более читаемым: сразу видно, что класс должен реализовать, что искать, где что править. Это делает процесс чтения кода и устранения ошибок проще. Работа с абстрактными методами — это фундамент для освоения полиморфизма в Java и других объектно-ориентированных языках. Как только вы начнете понимать и использовать эти методы, вы перейдете на новый уровень в программировании.
Какой в этом смысл?
Действительно, зачем прятать внутренности? Да потому что это спасет ваши нервы! Вы когда-нибудь пробовали чинить машину, пока она едет? Абстракция позволяет сосредоточиться на использовании компонентов, а не на их создании с нуля каждый раз. И если кто-то изменит внутреннюю реализацию, ваш код не сломается — он продолжит работать.
Перевод статьи «Java Abstract Class (Abstraction in Java)».