Интерфейсы являются основной частью языка программирования Java. Кроме JDK они используются еще и в шаблонах проектирования, а также множестве различных инструментах и фреймворках. Также интерфейсы обеспечивают абстракцию в Java.
Например, нам нужно создать рисунок, который состоит из нескольких фигур. Для этого мы можем создать интерфейс Shape
и определить методы для работы с объектами Shape. Для простоты, давайте определим только два метода — draw() -
чтобы нарисовать фигуру и метод getArea()
, который будет возвращать площадь фигуры.
Пример Java интерфейса
На основании вышеуказанных требований, наш интерфейс Shape
будет выглядеть следующим образом:
Shape.java
1 2 3 4 5 6 7 8 9 10 11 12 |
package ua.com.prologistic.interface; public interface Shape { //неявно public, static и final public String LABLE="Shape"; //методы интерфейса неявно abstract и public void draw(); double getArea(); } |
Основная информация об интерфейсах в Java
interface
— ключевое слово для создания интерфейса в Java.- Создать экземпляр интерфейса в Java нельзя.
- Интерфейс обеспечивает абсолютную абстракцию. В прошлых постах мы узнали об абстрактных классах в Java, которые также обеспечивают абстракцию, но абстрактные классы могут иметь реализаций метода, а интерфейс не может.
- Интерфейсы не могут иметь конструкторов, потому что мы не можем создать экземпляр интерфейса. Также интерфейсы не могут иметь методы с реализацией.
- По умолчанию любой атрибут интерфейса является public, static и final, так что нам не нужно определять модификаторы доступа к атрибутам. Если же вы попробуете это сделать, то компилятор жаловаться не будет.
- По умолчанию методы интерфейса неявно abstract и public. Это очень умное решение, потому что в интерфейсе метод не имеет реализации — этим занимаются подклассы, реализующие этот интерфейс.
- Интерфейс в Java не может быть подклассом у другого класса, но он может реализовать другой интерфейс.
public interface Shape extends Cloneable{} -
пример интерфейса, который наследует другой интерфейс. На самом деле Java обеспечивает множественное наследование интерфейсов — это означает, что интерфейс может наследовать несколько интерфейсов. - Ключевое слово
implements
используется классами для реализации интерфейса. - Класс, реализующий интерфейс, должен обеспечить реализацию всех его метода, если только это не абстрактный класс. Например, мы можем реализовать наш интерфейс в абстрактном классе. Вот пример:
ShapeAbs.java
1 2 3 4 5 6 7 8 9 10 |
package ua.com.prologistic.interface; public abstract class ShapeAbs implements Shape { @Override public double getArea() { return 0; } } |
- Программисты должны писать программы в терминах интерфейсов, а не реализаций, потому что в будущем переписать реализацию интерфейса можно будет и в новом классе.
Пример реализации интерфейса на Java
Теперь давайте посмотрим на реализацию интерфейса Shape:
Circle.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package ua.com.prologistic.interface; // класс Круг(Circle) реализует интерфейс Форма(Shape) public class Circle implements Shape { private double radius; public Circle(double r){ this.radius = r; } @Override public void draw() { System.out.println("Рисуем Круг"); } @Override public double getArea(){ // Вычисляем площадь return Math.PI*this.radius*this.radius; } public double getRadius(){ return this.radius; } } |
Обратите внимание, что класс Circle реализует все методы, определенные в интерфейсе, а также собственный метод getRadius()
. Реализация интерфейса может иметь несколько типов конструкторов. Давайте посмотрим другую реализацию интерфейса Shape.
Rectangle.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package ua.com.prologistic.interface; // Класс Прямоугольник(Rectangle) реализует интерфейс Форма(Shape) public class Rectangle implements Shape { private double width; private double height; public Rectangle(double w, double h){ this.width=w; this.height=h; } @Override public void draw() { System.out.println("Рисуем прямоугольник"); } @Override public double getArea() { return this.height*this.width; } } |
А теперь напишем программу для тестирования реализаций нашего интерфейса.
ShapeTest.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package ua.com.prologistic.interface; public class ShapeTest { public static void main(String[] args) { // реализуем интерфейс Shape shape = new Circle(10); shape.draw(); System.out.println("Площадь = " + shape.getArea()); //легко переключаемся с одной реализации на другую shape = new Rectangle(10,10); shape.draw(); System.out.println("Площадь = " + "+shape.getArea()); } } |
Результат работы программы будет такой:
1 2 3 4 |
Рисуем Круг Площадь = 314.1592653589793 Рисуем прямоугольник Площадь = 100.0 |
Преимущества интерфейсов в Java
- Интерфейс обеспечивает так называемый контракт для всех классов, которые реализуют интерфейс.
- Интерфейсы хороши для создания начальной точки и создания иерархии в проекте.
Недостатки интерфейсов в Java
Хотя интерфейсы дают программисту множество преимуществ, они также имеют и недостатки.
- Мы должны очень тщательно выбирать методы интерфейса во время проектирования любого проекта, потому что мы не можем добавить или удалять методы из интерфейса на более поздних этапах реализации проекта. Если же вы захотите удалить какие-то методы с интерфейса, то это приведет к ошибке компиляции во всех классах, которые реализуют интерфейс. Чтобы избежать этого, обычно создают множество интерфейсов, расширяющих базовый интерфейс, что усложняет поддержку такого кода.
- Если классы, которые реализуют интерфейс, имеют свои собственные методы, мы не можем использовать их непосредственно в коде, потому что тип объекта определяет интерфейс, у которого нет таких методов. Например, в таком коде мы получим ошибку компиляции кода для
shape.getRadius()
. Чтобы избежать ошибки, мы можем использовать приведение типов:
1 2 |
Circle c = (Circle) shape; c.getRadius(); |
Хотя приведение типов также имеет свои недостатки.
Интересно знать, что в Java 8 в интерфейсах появилась возможность определения методов по умолчанию, а также реализация статических методов в интерфейсах. Читайте об этом в следующих статьях на Javadevblog.com