JavaRush/Java блог/Java Developer/Зачем нужно наследование интерфейсов?
Павел
11 уровень

Зачем нужно наследование интерфейсов?

Статья из группы Java Developer
участников
Зачем нужны интерфейсы? Зачем нужно наследование интерфейсов? Зачем нужен полиморфизм? Для тех, кто почитал и понял, как делать наследование интерфейсов, но не понял, зачем. В прошлый раз, на примере обычной семьи Ивановых мы разобрали, зачем нужны интерфейсы. Продолжаем оцифровывать беспокойное семейство. У каждого человека есть какие-то привычки, которые он ни от кого не наследовал или никому не передавал по наследству - его личные привычки. У нас задача: наделить каждого члена семьи уникальными привычками. Переводим в плоскость Java: надо реализовать в классах уникальные методы, которые будут принадлежать только этим классам. Что же, вперед! Это Петя:
class Петя implements ПривычкиПапы, ПривычкиМамы {

//это личные Петины привычки
public void ковырятьВНосу () {
System.out.println("Ковырь-ковырь");
    }

//это унаследованные привычки
@Override
public void прихлюпывать() {
     System.out.println("Хлюп");
   }

@Override
public void поджимать () {
System.out.println("Поджать губки");
    }
}
Это Папа:
class Папа implements ПривычкиПапы {

//это личные Папины привычки
public void чесатьБороду () {
System.out.println("Чешу бороду");
    }

//это переданные привычки
   @Override
    public void прихлюпывать() {
     System.out.println("Хлюп");
   }
}
Это Мама:
class Мама implements ПривычкиМамы{

//это личные Мамины привычки
public void хлопатьРесницами () {
System.out.println("Хлоп-хлоп");
    }

//это переданные привычки
@Override
public void поджимать() {
System.out.println("Поджать губки");
    }
}
Идеально! Все работает как надо! В первой статье, говорилось, что программа — это отражение реального мира. Самое интересное свойство реальности – это все время меняться. Семья Ивановых не стала исключением, у них появилась лапочка-дочка по имени Маша. И она унаследовала от Мамы привычку хлопать ресницами, а от Папы прихлюпывать. Надо вносить изменения в нашу программу. Зачем нужно наследование интерфейсов? - 1Да ладно, это не так и сложно, главное мыслить логически. Ведь все знают зачем нужны интерфейсы. Сейчас создадим interface ПривычкиМаши, опишем там метод хлопатьРесницами() и прихлюпывать() имплементируем его к Маше и дело в шляпе. Ну и что, что методы с таким названием уже реализованы в других интерфейсах, один раз можно. Зачем нужно наследование интерфейсов? - 2Действительно, кто знает какие планы у семейства Ивановых, если родиться Сережа, который унаследует привычки от Папы, Мамы, ПраДедушки и еще кого-то из четвертого колена, каждый раз создавать интерфейс, типа: interface ПривычкиСережи, и там объявлять методы, которые уже могут быть объявлены сотни раз в других интерфейсах? Через пару, тройку поколений мы рискуем получить интерфейсы с кучей одинаковых методов, которые уже описаны в других интерфейсах, и если надо будет изменить наименование какой-нибудь привычки (а это вполне реально – ведь мир меняется), то как разобраться в этом спагетти, я не представляю. Остается только сидеть и мечтать о чуде. Зачем нужно наследование интерфейсов? - 3Вот если бы для каждой привычки был свой интерфейс. Двайте представим:
public interface ПривычкаПрихлюпывать {
    public void прихлюпывать();
}
public interface ПривычкаПоджимать {
    public void поджимать();
}
public interface ПривычкаКовырятьВНосу {
    public void ковырятьВНосу();
}
public interface ПривычкаХлопатьРесницами {
    public void хлопатьРесницами();
}
public interface ПривычкаЧесатьБороду {
    public void чесатьБороду();
}
А потом, можно было бы как в лего, с помощью множественного наследования из отдельных привычек набрать нужный нам интерфейс привычек отдельного члена семейства. Как-то так:
public interface ПривычкиМамы extends ПривычкаПоджимать, ПривычкаХлопатьРесницами {
    }
public interface ПривычкиПапы extends ПривычкаЧесатьБороду, ПривычкаХлюпать {
    }
public interface ПривычкиПети extends ПривычкаПоджимать, ПривычкаХлюпать,ПривычкаКовырятьВНосу {
    }
public interface ПривычкиМаши extends ПривычкаХлюпать, ПривычкаХлопатьРесницами {
    }
А потом просто имплементировать нужный интерфейс нужному классу, например, Маме:
class Мама implements ПривычкиМамы{
@Override
public void хлопатьРесницами () {
System.out.println("Хлоп-хлоп");
    }

@Override
public void поджимать() {
System.out.println("Поджать губки");
    }
}
Так же можно было бы поступить с Папой, Петей и Машей. И потом, при расширении семейства Ивановых, проблем бы с привычками не было, мы просто бы их тасовали через наследование на уровне интерфейсов, как ингредиенты в салате, и не плодили кучу методов с одинаковым наименованием. Эх, мечты, мечты… Зачем нужно наследование интерфейсов? - 4Нарисованный человек прав, так на самом деле можно - теперь симуляция семейства Ивановых спасена! Внимательный читатель, может задать вопрос: "А зачем плодить интерфейсы для каждого члена семьи? У нас есть набор действий - сразу имплементировать нужному классу." Представим что во многих параллельных мирах существуют двойники Пети, и всем Петям надо имплементировать interface ПривычкиПети
interface ПривычкиПети extends ПривычкаПоджимать, ПривычкаХлюпать,ПривычкаКовырятьВНосу

class ПетяВселеннаяХ implements ПривычкиПети
class ПетяВселеннаяY implements ПривычкиПети
// и т.д.
А если бы общего интерфейса не было
class ПетяВселеннаяХ implements ПривычкаПоджимать, ПривычкаХлюпать,ПривычкаКовырятьВНосу
class ПетяВселеннаяY implements ПривычкаПоджимать, ПривычкаХлюпать,ПривычкаКовырятьВНосу
// и т.д.
Получается более объемный повторяющийся код. Наследование интерфейсов делает приложение более гибким к изменениям, в частности — можно решить проблемы с повторяющимися методами. Еще раз обратите внимание, что множественное наследование интерфейсов — разрешено.
Комментарии (10)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Anonymous #3087360
Уровень 3
3 сентября 2022, 08:42
Автор! Очень классная статья! Всё понятно и по делу! Пиши ещё!
Иван
Уровень 23
24 июля 2022, 14:36
Очень классно! Спасибо Автору!
Максим
Уровень 32
30 апреля 2022, 10:27
Классный цикл статей, странно что не получили должного внимания, особенно в среде новичков
Василий Бабин Мракоборец в Дурмстранг Expert
27 ноября 2021, 07:36
Спасибо, хорошая статья! Но, есть ошибка которая несведущих введёт в заблуждение, тут в коде думаю надо: "Представим что во многих параллельных мирах существуют двойники Пети, и всем Петям надо имплементировать interface ПривычкиПети
interface ПривычкиПети extends ПривычкаПоджимать, ПривычкаХлюпать, ПривычкаКовырятьВНосу

class ПетяВселеннаяХ implements ПривычкиПети
class ПетяВселеннаяY implements ПривычкиПети
// и т.д.
"
Павел
Уровень 11
27 ноября 2021, 20:40
Спасибо!
Константин
Уровень 34
25 ноября 2021, 08:15
А зачем плодить интерфейсы для каждого члена семьи? У нас есть набор действий - сразу имплементировать нужному классу. Ну только если сохранить условие, что Петя наследует все привычки - тогда в его класс имплементируются интерфейсы привычки мамы и папы.
Павел
Уровень 11
25 ноября 2021, 09:16
Представим что во многих параллельных мирах существуют двойники Пети:
interface ПривычкиПети extends Привычка1, Привычка2, Привычка3 и тд.

class ПетяВселеннаяХ implements ПривычкиПети
class ПетяВселеннаяY implements ПривычкиПети
// и т.д.
А если бы общего интерфейса не было
class ПетяВселеннаяХ implements Привычка1, Привычка2, Привычка3 и тд.
class ПетяВселеннаяY implements Привычка1, Привычка2, Привычка3 и тд.
// и т.д.
Более объемный повторяющийся код получится. Так же можем через полиморфизм узнать различия в привычках разных Петь, оперируя только общим типом интерфейса ПривычкиПети
ПривычкиПети петя = //случайный Петя из любой вселенной;
петя.поджимать();
петя.хлюпать();
Без общего интерфеса
ПривычкаПоджимать привПетиПоджимать = //случайный Петя из любой вселенной;
привПетиПоджимать.поджимать();
ПривычкаХлюпать привПетиХлюпать = //случайный Петя из любой вселенной;
привПетиХлюпать.хлюпать();
// и т.д.
И потом: В общем интерфейсе можно объявить метод - свой для этого интерфейса. Для interface ПривычкиПети мне сейчас сложно придумать бизнес пример, поэтому переименую его в interface Петя, пусть он наследует интерфейсы привычек. В interface Петя можно объявить например метод getМестоЖительстваПети(); - что бы узнать где живет каждый Петя в каждой вселенной, ведь вселенные разные и названия улиц там могут быть разные. И в коде, использовать этот метод (getМестоЖительстваПети();) через полиморфизм.
Петя петя = //случайный Петя из любой вселенной;
String местоЖительства = петя.getМестоЖительстваПети();
В следующей статье про полиморфизм написано. Кстати, надо будет теперь дописать ее) спасибо за вопрос
Василий Бабин Мракоборец в Дурмстранг Expert
27 ноября 2021, 07:50
Сначала написал свой комментарий (выше). А потом прочитал Ваш и понял, что Вы дополнили статью, а я как бы сумничал. )) Но, тут у Вас правильно, а там, думаю, отпечатались.
Павел
Уровень 11
29 ноября 2021, 05:54
На самом деле я рад, что кто то смотрит статьи и поправляет. Комментарии, исправления и уточнения помогают делать материал лучше
Anonymous #2583212 Backend Developer в Open Code
22 ноября 2021, 14:00
Хороший забавный пример)