JavaRush /Курсы /Java Syntax Pro /Суть интерфейсов

Суть интерфейсов

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

1. Способности

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

Класс — это, чаще всего модель какого-то конкретного объекта. Интерфейс же больше соответствует не объектам, а их способностям или ролям.

Суть интерфейсов

Например, такие вещи, как машина, велосипед, мотоцикл и колесо лучше всего представить в виде классов и объектов. А такие их способности, как «могу ездить», «могу перевозить людей», «могу стоять», лучше представить в виде интерфейсов. Вот несколько примеров:

Код Описание
interface Movable
{
   void move(String newAddress);
}
соответствует способности передвигаться
interface Driveable
{
   void drive(Driver driver);
}
соответствует способности управляться водителем
interface Transport
{
   void addStuff(Object stuff);
   Object removeStuff();
}
соответствует способности перевозить грузы
class Wheel implements Movable
{
   ...
}
класс Wheel (колесо) обладает способностью передвигаться
class Car implements Movable, Driveable, Transport
{
   ...
}
класс Car (машина) обладает способностью передвигаться, управляться человеком и перевозить грузы
class Skateboard implements Movable, Driveable
{
   ...
}
класс Skateboard (скейтборд) обладает способностью передвигаться и управляться человеком


2. Роли

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

Весь смысл в том, что вам не нужно писать код для взаимодействия всех классов со всеми. Вам достаточно взаимодействовать с их ролями (интерфейсами).

Представьте, что вы дрессируете домашних животных, каждое из которых может иметь несколько разных способностей. И вы поспорили с соседом, чьи животные громче кричат. Вы просто берете всех, у которых есть способность «голос», и командуйте им: Голос!.

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

Код Описание
interface Звучание
{
   void голос();
}
Способность Звучание. Понимает команду голос — имеет соответствующий метод.
class Кот implements Звучание
{
   void голос()
   {
      println("МЯУ");
   }
}

class Собака implements Звучание
{
   void голос()
   {
      println("ГАВ");
   }
}

class Рыбка
{
   ...
}
Животные, у которых есть эта особенность.

Для удобства мы дали классам имена на русском. Такое допускается в Java, но крайне нежелательно.













Наша Рыбка не обладает способностью говорить (не реализует интерфейс Звучание).

public static void main(String[] args)
{
   // добавляем всех животных в список
   ArrayList pets = new ArrayList();
   pets.add(new Кот());
   pets.add(new Собака());
   pets.add(new Рыбка());

   // орать, если есть такая способность
   for(Object pet: pets)
   {
      if (pet instanceof Звучание)
      {
         Звучание крикун = (Звучание) pet;
         крикун.голос();
      }
   }
}
И как дать им команду?

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

А в совокупности с полиморфизмом — это вообще бомба.



3. default реализация в методах интерфейсов

Абстрактные классы могут иметь переменные и реализацию методов, но для них множественное наследование запрещено. Интерфейсы не могут иметь переменные и реализации методов, и для них множественное наследование разрешено.

Можно эту ситуацию выразить в таблице:

Способность Абстрактные классы Интерфейсы
Переменные
Реализация методов
Множественное наследование

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

К тому же, проблемы с множественным наследованием в первую очередь из-за переменных. В общем, решили и сделали. Начиная с JDK 8, в Java появилась возможность добавлять в интерфейсы методы с реализацией.

Новая актуальная таблица (для JDK 8 и выше):

Способность Абстрактные классы Интерфейсы
Переменные
Реализация методов
Множественное наследование

Теперь и в абстрактных классах, и в интерфейсах можно объявлять как методы с реализацией, так и без нее. И это отличная новость!

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

Для простоты приведем эту информацию в виде небольшой таблички:

Способность Абстрактные классы Интерфейсы
Методы без реализации abstract
Методы с реализацией default

Проблема

С помощью интерфейсов с методами можно значительно упростить иерархии многих классов. Например, абстрактные классы InputStream и OutputStream можно объявить интерфейсами! Это позволит использовать их гораздо чаще и гораздо удобнее.

Но в мире уже написаны десятки миллионов (миллиарды?) Java-классов. И если начать менять стандартные библиотеки, то есть риск, что что-то может поломаться. Например, всё! 😛

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

Например, если от интерфейса с методом унаследовать второй интерфейс и в нем объявить этот же метод, но без реализации, то реализация из первого метода до класса не дойдет. Пример:

interface Pet
{
   default void meow()
   {
      System.out.println("Мяу");
   }
}

interface Cat extends Pet
{
   void meow(); // тут мы перекрыли дефолтную реализацию ее отсутствием
}

class Barsik implements Cat
{
}

Код не скомпилируется, т.к. в классе Barsik не реализован метод meow().



Комментарии (183)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Сергей Сак Уровень 16
16 сентября 2025

И вот некоторым программистам очень хотелось, чтобы у интерфейсов была возможность иметь реализацию методов
Не то, чтобы хотелось. Это скорее была необходимость. Была необходимость добавить новые методы в уже существующие интерфейсы. И если бы разработчики джавы это сделали, то сломалась бы куча программ и всем, кто использовал эти интерфейсы, пришлось бы дописывать реализацию этих новых методов. И чтобы этого не произошло, было принято решение добавить в интерфейсы методы с реализацией по умолчанию, благодаря чему миллионы программ не пострадали.
Anonymous #3585174 Уровень 33
22 июля 2025
like
4el0vek3 Уровень 36
21 июля 2025
Лекции стали короче(
Aura Уровень 23
10 июля 2025
Боги, люди здесь реально комиксы обсуждают... =) Забавно
4el0vek3 Уровень 36
22 июля 2025
Ради них проходят уровни
Exaltyr777 Уровень 25
4 августа 2025
Какие комиксы, я что-то пропустил?
Aura Уровень 23
5 августа 2025
Которые почти в каждой лекции есть по парочке страниц
Anonymous #3312942 Уровень 32
21 июня 2025
Дорогие администраторы, было бы уместнее заменить в лекции: 0) Чтобы не вводить в заблуждение заменить "interface Movable { void move(String newAddress);}" на ".... (String move)" 1) "соответствует способности управляться водителем" на "... управление водителем" 2) "interface Transport" на "Transportable" ? и тут же 3) "соответствует способности перевозить грузы" на "возможный к транспортировке" ?
Anand Уровень 32
29 апреля 2025
Анжелика...
26 апреля 2025
Что за дичь пошла в этом сюжете с Амиго и Диего?)))
Marat Safiianov Уровень 1
14 апреля 2025
Ай-яй-яй, почему же переменная ArrayList pets в примере про интерфейс объявляется не через интерфейс List?
Cryptosin Уровень 24
14 февраля 2025

Для удобства мы дали классам имена на русском. 
марк Уровень 25
25 февраля 2025
+
Олег Сычев Уровень 29
2 мая 2025
Вот да))) Имена классов или переменных на русском в коде только путают)))😅
Victor Уровень 39
11 февраля 2025
Первая задача, написал main - действительно всё работает. public class Solution { public static void main(String[] args) { Bus myBus = new Bus(); myBus.start(); myBus.move(); myBus.stop(); Car myCar = new Car(); myCar.start(); myCar.move(); myBus.stop(); } }