Интерфейсы в ООП (Java), по-простому?

Интерфейсы в ООП (Java), по-простому?

Объясните по-простому, на пальцах, зачем и для чего нужны интерфейсы (Java)? Все эти заумные книжные определения и формулировки, ясности совсем не прибавляют.

16 ответов 16

Общее определение: Интерфейс — это совокупность методов и правил взаимодействия элементов системы. Другими словами, интерфейс определяет как элементы будут взаимодействовать между собой.

  • Интерфейс двери — наличие ручки;
  • Интерфейс автомобиля — наличие руля, педалей, рычага коробки передач;
  • Интерфейс дискового телефона — трубка + дисковый набиратель номера.

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

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

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

Предположим, у вас в программе есть следующие типы:

а сейчас посмотрим, как можно пользоваться тем, что у нас есть:

Как видите, используем мы их одинаково, но суть кроется в реализации методов:

С одной стороны, тот факт, что SomeCar наследует интерфейс CarWithKpp (а посредством последнего еще и Car ), позволяет нам использовать его для работы с методами testAction1, testAction2 . Интерфейсы, которые реализованы (имплементированы) в классе SomeCar — предоставляют доступ к правильному его использованию. А еще использование интерфейса в сигнатуре метода гарантирует, что вы получите именно тот тип, который вам нужен.

Обратная сторона медали состоит в том, что интерфейс накладывает ограничения на использование класса. Примером этому является то, что в методе testAction2 получить доступ к методу getKpp уже невозможно. Таким образом, можно скрыть методы и свойства, которые объявлены в интерфейсе CarWithKpp , а также методы, объявленные в классе SomeCar (если их нет в интерфейсе). Оба метода могут использовать только тот набор "средств", которые им доступны (это определяется интерфейсом).

Вам может показаться странным, но это именно то, что отличает человека от животного — использование интерфейсов вместо классов. Вы наверняка помните классический опыт с обезьяной, которую приучили гасить огонь водой из ведёрка; а потом поставили ведёрко на плот посреди бассейна, но обезьяна всё равно бегала по мостику на плот и черпала воду из ведёрка, вместо того, чтобы черпать воду прямо из бассейна. То есть обезьянка использовала класс Вода-в-Ведёрке вместо интерфейса Вода (и даже больше, скажу по секрету: вместо интерфейса Средство-для-Тушения).

Когда мы мыслим классами — уподобляемся животным. Люди мыслят (и программируют) интерфейсами.

По простому говорите? Ну ок, правда сейчас тут начнут плеваться всякие товарищи типо гуру :)

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

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

Пример: есть объект стол, у которого есть методы работы с ним: как то есть поесть сидя за ним, накрыть на нем хавчик, поставить, собрать, отпилить ножки и проч. Но этот же объект стол можно рассматривать как интерфейс мебель (на языке ООП это называется класс типа стол реализующий интерфейс типа мебель: class Table implements Furniture . Понятно, что не на всякой мебели можно поесть или отпилить ножку, но что уж точно так это то что мебель можно поставить и собрать.

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

P.S. Кстати, любимый вопрос интервьюеров на собеседовании: что имеет более высокий уровень абстракции - класс, абстрактный класс или интерфейс? Правильный ответ - интерфейс

Понимание интерфейсов придёт со временем. Сколько не читай, сколько не объясняй, Вы Сами должны понять ту гибкость, тот масштаб действий, которые они предоставляют программисту. Пытайтесь их использовать. Библиотека классов Java предоставляет интерфейсы для реализации. Попробуйте их изучить, возможно это поможет Вам уловить всю мощь которую предоставляет программирование с использованием интерфейсов.

Интерфейс - это описание того, что может и должен уметь делать объект класса, который реализует этот интерфейс.

Не будем оригинальны и возьмем для примера дверь.

Что обычный человек может сделать с дверью? Открыть и закрыть.

Соответственно интерфейс для нее будет такой:

А теперь следите за руками. Объекту человек нужно пройти через дверь. Важно ему какая дверь перед ним дверь, деревянная, железная, с окошком, открывается она на себя или от себя, а может вообще сдвигается в бок? Нет, не важно. Ему важно, чтобы ее в принципе можно было открыть.

По этому, в классе "Человек" мы принимаем в метод "Пройти через дверь" не какую-то конкретную дверь, а в принципе "Дверь", потому что знаем, что у нее есть метод "Открыть".

Соответственно ниже пример двух объектов, реализующие интерфейс "Дверь" и которые можно передать "Человеку" в метод "Пройти через дверь", но реализующие разную логику для метола "Открыть".

Интерфейсом** объекта мы назовём набор операций (методов), которые он может совершать или которые можно совершать над ним. Например, интерфейс числа 3 называется, собственно, «Число» и включает в себя набор операций сложения, вычитания, умножения и деления. Реализовать этот интерфейс может любое количество типов/классов, например, типы ЦелоеЧисло, ВещественноеЧисло, КомплексноеЧисло, а также такие неочевидные типы как Интервал или Полином. В то же время, один и тот же тип может реализовать более чем один интерфейс. Так, ЦелоеЧисло кроме интерфейса Число может реализовать интерфейс Перечислимый – для этого в классе ЦелоеЧисло будет необходимо всего лишь доопределить операции «следующий» и «предыдущий».

Объясню без деталей.

Допустим, мы создали Framework, который определяет, совершил ли пользователь double-click по экрану.

Там мы определили функцию: что_делать_если_пользователь_кликнул_2_раза_по_экрану() .

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

Функцию: что_делать_если_пользователь_кликнул_2_раза_по_экрану() засовываем в интерфейс.

И, таким образом, сам момент двойного клика по экрану определяет наш фреймворк, а вот что делать (рисовать звездочки на экране, запустить проигрывание музыки и т.д.) после этого события решает программист, который реализует наш интерфейс.

Польза: программисту не надо думать, как словить double-click . За ним только реализация ответа на это событие.

Представьте себе группу друзей. Все они люди и имеют свои особенности, профессии(кто-то шахтер, кто-то бармен и т.д.). Тут братва пришла в бар посидеть выпить пивка. А бар такой - если вы хотите быть клиентами бара - не вопрос реализуйте наш интерфейс "Клиент", и вот вам свод действий которые вы должны реализовать являясь клиентом: Купить пивко, сесть за стол, выпить пивко, заплатить счет. Все друзья разные, кто-то врач, кто-то сантехник, кто-то без руки, кто-то с татухой на лбу(странная компашка знаю)), но когда они приходят в бар - все они "клиенты" и обязаны реализовать интерфейс "Клиент" с его методами. Да, каждый из них реализует, интерфейс по своему - кто-то даст на чай, когда будет оплачивать счет, кто-то разобьет бутылку об лоб, когда будет пить пивко ну и т.д.(это уже полиморфизм), но все они клиенты в данный момент и сотрудники бара взаимодействуют с ними как с клиентами, а не Васей(шахтером), Петей(алкоголиком). и.д. В общем интерфейсы нужны, что бы связать группу не связанных объектов, которые обязаны реализовать поведение того интерфейса, что бы можно было взаимодействовать с ними через этот общий интерфейс.

"зачем и для чего":

1) Взаимодействие с окружающим миром. Программы пишет не один человек, они состоят не из одного класса и зачастую не из одного пакета и модуля. И суть программы в том, что код разных авторов, разных модулей взаимодействует между собой. Самый простой пример: вы пользуетесь сторонними библиотеками. Вы нашли нужный вам класс, подключили библиотеку, которая его содержит и вызываете оттуда методы. В какой-то момент автор библиотеки решил изменить свой код, разве это редкость? Исправить выявленные баги, улучшить, расширить функционал. И это может оказаться для вас глубокой неожиданностью: ваш-то код завязан на его код! И ваш код внезапно ломается.

Чтобы такого не происходило, чтобы чужой открытый код мог использоваться сторонними разработчиками без неожиданностей, придумали интерфейсы. Интерфейс — это объявление функционала. Имплементация классом интерфейса — это гарантия реализации функционала. Если класс имплементирует некоторый интерфейс, то он обещает, что в нем есть объявленные в интерфейсе методы, они принимают объявленные параметры и возвращает объявленное значение. У вас может возникнуть вопрос: но ведь интерфейсы — это тоже код и его так же, как и класс, можно изменить. Можно. Но на практике это происходит крайне редко, интерфейс - это заявленный контракт и мы понимаем, что наш интерфейс, если он открыт, может использоваться не только нами.

2) В Java в качестве ссылки на переменную может выступать интерфейс. Например, уместен следующий метод:

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

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

📎📎📎📎📎📎📎📎📎📎