> For the complete documentation index, see [llms.txt](https://andrey-ivantsov.gitbook.io/java/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://andrey-ivantsov.gitbook.io/java/interfeisy.md).

# Интерфейсы

[**Интерфейс**](http://proglang.su/java/interfaces) — это ссылочный тип в Java. Он схож с классом. Это совокупность абстрактных методов. Класс реализует интерфейс, таким образом наследуя абстрактные методы интерфейса.

Вместе с абстрактными методами интерфейс в Java может содержать константы, обычные методы, статические методы и вложенные типы. Тела методов существуют только для обычных методов и статических методов.

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

Написание интерфейса схоже с написанием класса. Но класс описывает атрибуты и поведения объекта. И интерфейс содержит поведения, которые класс реализует.

Если класс, реализующий интерфейс, не является абстрактным, все методы интерфейса должны быть определены в классе.

### Объявление интерфейсов <a href="#obyavlenie-interfeysov" id="obyavlenie-interfeysov"></a>

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

#### Пример 1 <a href="#primer-1" id="primer-1"></a>

```java
/* File name : NameOfInterface.java */
import java.lang.*;
// Любое количество запросов импорта

public interface NameOfInterface { //создание интерфейса
   // Любое количество полей final и static
   // Любое количество объявлений абстрактных методов
}
```

Интерфейсы имеют следующие свойства:

* Интерфейс абстрактный косвенно. Вам не нужно использовать ключевое слово abstract во время объявления интерфейса.
* Каждый метод в интерфейсе косвенно абстрактным, поэтому ключевое слово abstract не нужно.
* Методы в интерфейсе косвенно публичны.

#### Пример 2 <a href="#primer-2" id="primer-2"></a>

```java
/* File name : Animal.java */
interface Animal {
   public void eat();
   public void travel();
}
```

### Реализация интерфейса <a href="#realizaciya-interfeysa" id="realizaciya-interfeysa"></a>

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

Класс использует ключевое слово implements для реализации интерфейса. Ключевое слово **implements** появляется при объявлении класса в его расширенной части.

#### Пример <a href="#primer" id="primer"></a>

```java
/* File name : MammalInt.java */
public class MammalInt implements Animal {

   public void eat() {
      System.out.println("Млекопитающее кушает");
   }

   public void travel() {
      System.out.println("Млекопитающее путешествует");
   } 

   public int noOfLegs() {
      return 0;
   }

   public static void main(String args[]) {
      MammalInt m = new MammalInt();
      m.eat();
      m.travel();
   }
}
```

Получим следующее:

```
Млекопитающее кушает
Млекопитающее путешествует
```

При переопределении методов в интерфейсе, нужно следовать некоторым правилам:

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

При реализации интерфейсов есть некоторые правила:

* Класс может реализовать более одного интерфейса за раз.
* Класс может расширить только один класс, но реализовать множество интерфейсов.
* Интерфейс может расширить другой интерфейс таким же образом, как класс расширяет другой класс.

### Расширение интерфейсов <a href="#rasshirenie-interfeysov" id="rasshirenie-interfeysov"></a>

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

Приведённый интерфейс Sports расширен интерфейсами Hockey и Football.

#### Пример <a href="#primer" id="primer"></a>

```java
// Filename: Sports.java
public interface Sports {
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}

// Filename: Football.java
public interface Football extends Sports {
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}

// Filename: Hockey.java
public interface Hockey extends Sports {
   public void homeGoalScored();
   public void visitingGoalScored();
   public void endOfPeriod(int period);
   public void overtimePeriod(int ot);
}
```

Интерфейс Hockey имеет четыре метода, но он наследует два из Sports; таким образом, класс, который реализует Hockey, должен реализовать все шесть методов. Подобно этому, класс, который реализует Football, должен определить три метода из Football и два метода из Sports.

### Расширение множества интерфейсов <a href="#rasshirenie-mnozhestva-interfeysov" id="rasshirenie-mnozhestva-interfeysov"></a>

Класс в Java может расширить только один родительский класс. Множественное наследование невозможно. Однако интерфейсы не классы, и интерфейс может расширить более чем один родительский интерфейс.

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

Например, если интерфейс Hockey расширил и Sports, и Event, то объявление выглядело бы так:

```java
public interface Hockey extends Sports, Event
```

### Интерфейсы тегов <a href="#interfeysy-tegov" id="interfeysy-tegov"></a>

Самое распространённое использование расширения интерфейсов происходит тогда, когда родительский интерфейс не содержит каких-либо методов. Например, интерфейс MouseListener в пакете java.awt.event расширил java.util.EventListener, который определяется так:

```java
package java.util;
public interface EventListener
{}
```

Интерфейс без методов в нём называется интерфейсом тегов. Есть две простые дизайнерские цели для интерфейсов тегов:

**Создаёт общего родителя** – как в случае с интерфейсом EventListener, который расширяется множеством других в Java API, вы можете использовать интерфейс тегов, чтобы создать общего родителя среди группы интерфейсов. Например, когда интерфейс расширяет EventListener, то JVM знает, что этот конкретный интерфейс будет использоваться в сценарии делегирования событий.

**Добавляет тип данных в класс** – эта ситуация является источником термина «тегирование». Класс, который реализует интерфейс тегов, не должен определять какие-либо методы (т.к. интерфейс не имеет таковых), но класс становится типом интерфейса через полиморфизм.
