Интерфейс (Java)

Материал из Циклопедии
Перейти к навигации Перейти к поиску

 → Интерфейс (объектно-ориентированное программирование)

Интерфейс — важная конструкция для реализации объектно-ориентированного программирования в языке программирования Java.

В отличие от C++, Java не позволяет наследовать больше одного класса. В качестве альтернативы множественному наследованию существуют интерфейсы. Каждый класс в Java может реализовать любой набор интерфейсов. Порождать объекты от интерфейсов в Java нельзя. Доступно расширение одного интерфейса другим по аналогии с наследованием.

Объявление интерфейсов[править]

Объявление интерфейсов очень похоже на упрощённое объявление классов.

Оно начинается с заголовка. Сначала указываются модификаторы. Интерфейс может быть объявлен как public, и тогда он будет доступен для общего использования, либо модификатор доступа может не указываться, в этом случае интерфейс доступен только для типов своего пакета. Модификатор abstract для интерфейса не требуется, поскольку все интерфейсы являются абстрактными классами. Его можно указать, но делать этого не рекомендуется, чтобы не загромождать код.

Далее записывается ключевое слово interface и имя интерфейса.

После этого может следовать ключевое слово extends и список интерфейсов, от которых будет наследоваться объявляемый интерфейс. Родительских типов (классов и/или интерфейсов) может быть много — главное, чтобы не было повторений, и чтобы отношение наследования не образовывало циклической зависимости.

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

Затем в фигурных скобках записывается тело интерфейса.

Пример объявления интерфейса (Ошибка если Colorable и Resizable классы: The type Colorable and Resizable cannot be a superinterface of Drawable; a superinterface must be an interface): <source lang="java"> public interface Drawable extends Colorable, Resizable { } </source>

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

<source lang="java"> public interface Directions {

 int RIGHT=1;
 int LEFT=2;
 int UP=3;
 int DOWN=4;

} </source>

Все методы интерфейса являются public abstract, и эти модификаторы также необязательны.

<source lang="java"> public interface Moveable {

 void moveRight();
 void moveLeft();
 void moveUp();
 void moveDown();

} </source>

Как видно, описание интерфейса гораздо проще, чем объявление класса.

Реализация интерфейса[править]

Для реализации интерфейса он должен быть указан при декларации класса с помощью ключевого слова implements. Пример:

<source lang="java"> interface I {

  void interfaceMethod();

}

public class ImplementingInterface implements I {

  void interfaceMethod()
  {
     System.out.println("Этот метод реализован из интерфейса I");
  }

}

public static void main(String[] args) {

  ImplementingInterface temp = new ImplementingInterface();
  temp.interfaceMethod();

} </source>

Каждый класс может реализовывать любые доступные интерфейсы. При этом в классе должны быть реализованы все абстрактные методы, появившиеся при наследовании от интерфейсов или родительского класса, чтобы новый класс мог быть объявлен неабстрактным.

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

<source lang="java"> interface A {

 int getValue();

}

interface B {

 double getValue();

}

interface C {

 int getValue();

}

public class Correct implements A, C // класс правильно наследует методы с одинаковой сигнатурой {

  int getValue()
  {
     return 5;
  }

}

class Wrong implements A, B // класс вызывает ошибку при компиляции {

  int getValue()
  {
     return 5;
  }
  double getValue()
  {
     return 5.5;
  }

} </source>

Ссылки[править]