Для чего нужен интерфейс в java
Перейти к содержимому

Для чего нужен интерфейс в java

  • автор:

Для чего нужен интерфейс в java

JavaRush — это интерактивный онлайн-курс по изучению Java-программирования c нуля. Он содержит 1200 практических задач с проверкой решения в один клик, необходимый минимум теории по основам Java и мотивирующие фишки, которые помогут пройти курс до конца: игры, опросы, интересные проекты и статьи об эффективном обучении и карьере Java‑девелопера.

Подписывайтесь

Язык интерфейса

«Программистами не рождаются» © 2023 JavaRush

Скачивайте наши приложения

«Программистами не рождаются» © 2023 JavaRush

Этот веб-сайт использует данные cookie, чтобы настроить персонально под вас работу сервиса. Используя веб-сайт, вы даете согласие на применение данных cookie. Больше подробностей — в нашем Пользовательском соглашении.

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

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

Отслеживать
51.2k 86 86 золотых знаков 266 266 серебряных знаков 505 505 бронзовых знаков
задан 15 авг 2012 в 15:51
760 2 2 золотых знака 8 8 серебряных знаков 22 22 бронзовых знака
Вопросом на вопрос: вы программируете без использования интерфейсов?
15 авг 2012 в 15:56
если трудно объяснить словами, можно на примере простого исходника.
15 авг 2012 в 16:22

16 ответов 16

Сортировка: Сброс на вариант по умолчанию

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

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

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

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

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

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

// несколько базовых интерфейсов, они пустые, // т.к. их наполнение на данный момент не существенно interface Rul <> interface Pedal <> interface Kpp <> // интерфейс описывает взаимодействие с автомобилем - т.е. его интерфейс // предоставляет другим объектам доступ к рулю и педалям // (по сути этот интерфейс соответствует автомобилю с коробкой автоматом) interface Car < Rul getRul(); Pedal[] getPedali(); >// этот интерфейс расширяет базовый // и предоставляет доступ еще и к коробке передач interface CarWithKPP extends Car < Kpp getKpp(); >// а здесь у нас сам автомобиль // реализации методов опущены т.к. не существенно class SomeCar implements CarWithKpp

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

// создаем новый объект SomeCar instance = new SomeCar(); // делаем какие-то действия над объектом testAction1(instance); testAction2(instance); 

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

void testAction1(CarWithKpp c) < c.getRul(); // можно c.getPedali(); // можно c.getKpp(); // можно >void testAction2(Car c) < c.getRul(); // можно c.getPedali(); // можно c.getKpp(); // нельзя, ошибка компиляции. этот метод не определен в интерфейсе Car >

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

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

Отслеживать
28.5k 12 12 золотых знаков 59 59 серебряных знаков 118 118 бронзовых знаков
ответ дан 15 авг 2012 в 21:38
6,252 16 16 серебряных знаков 21 21 бронзовый знак
Kpp — это шикарно 🙂
16 авг 2012 в 8:04
ну так наверно автомат/неавтомат
16 авг 2012 в 8:06

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

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

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

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

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

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

Отслеживать
ответ дан 15 авг 2012 в 16:09
81.2k 7 7 золотых знаков 72 72 серебряных знака 153 153 бронзовых знака

Прочитал. Критикую. Пример с воротами — неудачный, со столом — плохой. Так как интерфейсы это больше как «набор правил/ рычагов воздействия на обьекты» одного типа, а у тебя примеры больше подходят к extened. У класса мебель могут быть свойтва — тип — дерево, пластик; высота, вес, цена, стул — наследник на 4х ножках, а у интерфейса для работы с мебелью методы типа — погрузить в машину, выкинуть, продать. Отсюда интерфейс — это розетка, за которой не видно как идет ток, какого он напряжения, как там провода перепутаны, но к нему всегда можно подключить любую технику

15 авг 2012 в 17:10
@Gorets ну я же говорил, что найдутся типо гуру с критикой 🙂
15 авг 2012 в 17:39
@Barmaley, с гуру-критиками — гениальный ход. Надо будет взять на вооружение.
15 авг 2012 в 19:29

@Barmaley, с воротами и дверями в них не очень удачно. Однако образ интересный. Я бы по аналогии сказал, что есть множество дверей в здании и «волшебные очки» (это интерфейс), которые показывают двери. Чтобы все заработало виртуальным (в очках) дверям должны соответствовать реальные. В то же время «лишние» реальные двери через очки не видны, но никому и не мешают. Плюс, через эти очки можно смотреть на разные здания.

15 авг 2012 в 19:55
. а если принять таблеточку LSD — получится IoC контейнер.
15 авг 2012 в 20:22

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

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

Отслеживать
ответ дан 1 окт 2014 в 5:33
249 2 2 серебряных знака 6 6 бронзовых знаков

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

1 окт 2014 в 9:42

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

Отслеживать
ответ дан 15 авг 2012 в 16:12
ivan milyutkin ivan milyutkin
255 1 1 серебряный знак 5 5 бронзовых знаков

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

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

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

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

interface Door

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

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

class Human < public void goThruDoor(Door door)< if(door.isClosed())< if(!door.open())< throw new Exception("дверь не открывается :("); >> goForward(); door.close(); > > 

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

class WoodenDoor implements Door < private boolean closed = false; public boolean isClosed()< return closed; >public boolean open() < if(!closed) return false; closed = false; return true; >public boolean close() < if(closed) return false; closed = true; return true; >> class LockedDoor implements Door < private boolean locked = true; private boolean closed = false; public boolean isClosed()< return closed; >public boolean open() < if(locked||!close) return false; closed = false; return true; >public boolean close() < if(closed) return false; closed = true; return true; >> 

Отслеживать
ответ дан 9 сен 2017 в 10:24
13.9k 4 4 золотых знака 33 33 серебряных знака 51 51 бронзовый знак

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

Отслеживать
ответ дан 15 авг 2012 в 15:57
12.4k 1 1 золотой знак 20 20 серебряных знаков 43 43 бронзовых знака
А где размещён при этом интерфейс Перечислимый ? В Число ?
28 ноя 2013 в 13:16

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

Отслеживать
ответ дан 25 ноя 2019 в 13:59
Влад Леонидов Влад Леонидов
527 3 3 серебряных знака 12 12 бронзовых знаков

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

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

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

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

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

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

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

Отслеживать
1,745 9 9 золотых знаков 19 19 серебряных знаков 28 28 бронзовых знаков
ответ дан 9 сен 2017 в 8:38
483 7 7 серебряных знаков 18 18 бронзовых знаков

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

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

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

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

public void letsIterateABit(Iterable something) < //Iterable — это интерфейс, у которого есть метод iterator(). //какой-то код something.iterator(); //еще какой-то код >

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

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

Введение в интерфейсы Java

Java — очень сложно, так говорят… Правда ли это?

7 фактов про Java

Java разработчик: как стать за месяц?

Операторы в Java: Понимание, применение и перегрузка

Нужен ли Spring новичку Java? Что почитать?

Интерфейсы являются важной составной частью языка программирования Java. Это мощный механизм для определения контрактов, которые классы должны соблюдать. В этой статье мы рассмотрим основные аспекты интерфейсов в Java, начиная с их объявления и использования и заканчивая статистическими методами.

Что такое интерфейс в Java

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

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

Java Start: Ваш Билет в Мир Программирования Java!

�� Что вы получите с Java Start:

  • Просто усвояемый материал, даже если вы начинающий.
  • Уроки, специально разработанные для вашего понимания.
  • Поддержка в чате Slack.

�� Для кого этот курс:

  • Новички, мечтающие стать Java-разработчиками.
  • Люди с хорошими навыками владения компьютером и чтения на английском.

�� Почему выбирают Java Start:

  • Прохождение курса в 2-4 недели.
  • Онлайн формат.
  • Разработчик курса: Сергей Немчинский!

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

Для объявления интерфейса в Java используется ключевое слово «interface», за которым следует имя интерфейса. Затем в фигурных скобках перечисляются абстрактные методы, которые должны быть реализованы в классах, использующих данный интерфейс. Например:

```java public interface MyInterface < void myMethod1(); void myMethod2(); >```

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

Интерфейсы также могут наследовать другие интерфейсы с помощью ключевого слова «extends». Это позволяет создавать иерархию интерфейсов и определять общую функциональность для нескольких интерфейсов.

Имплементация интерфейсов в Java

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

Для имплементации интерфейса в классе используется ключевое слово «implements», за которым указывается имя интерфейса. Затем в фигурных скобках следует реализация каждого метода, объявленного в интерфейсе. Например:

```java public interface MyInterface < void myMethod(); >public class MyClass implements MyInterface < @Override public void myMethod() < // Реализация метода myMethod >> ```

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

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

Интерфейсы и наследование в Java

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

Интерфейсы и наследование в Java

Похожие материалы
Java — очень сложно, так говорят… Правда ли это?
7 фактов про Java
Java разработчик: как стать за месяц?
Операторы в Java: Понимание, применение и перегрузка
Нужен ли Spring новичку Java? Что почитать?
Что такое интерфейс в Java?

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

Могу ли я создать объект интерфейса?

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

Что такое множественное наследование в контексте интерфейсов?

В Java класс не может наследоваться от нескольких классов, но может реализовывать несколько интерфейсов. Это позволяет обойти ограничение одиночного наследования.

Могут ли интерфейсы содержать реализацию методов?

До Java 8 интерфейсы могли содержать только абстрактные методы. Начиная с Java 8, интерфейсы могут содержать методы с реализацией, называемые «default» методами.

Что такое функциональный интерфейс?

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

Могут ли интерфейсы содержать переменные?

Да, интерфейсы могут содержать переменные, но они автоматически становятся public, static и final.

Интерфейсы Java – что это такое?

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

Вы можете использовать их как способ достижения полиморфизма.

Пример интерфейса Java

Вот простой пример интерфейса Java:

public interface MyInterface

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

Приведенный выше пример содержит одну переменную и один метод. Доступ к переменной можно получить непосредственно из интерфейса, например так:

System.out.println(MyInterface.hello);

Как видите, доступ к переменной очень похож на доступ к статической переменной в классе.

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

Реализация интерфейса

Вот класс, который реализует интерфейс MyInterface, показанный выше:

public class MyInterfaceImpl implements MyInterface < public void sayHello() < System.out.println(MyInterface.hello); >>

Обратите внимание, реализует часть MyInterface вышеупомянутого объявления класса. Это сообщает компилятору Java, что класс MyInterfaceImpl реализует интерфейс MyInterface.

Класс, реализующий интерфейс, должен реализовывать все методы, объявленные в нем. Методы должны иметь точно такую же сигнатуру(имя + параметры), как объявлено. Класс не должен реализовывать(объявлять) переменные интерфейса. Только методы.

Экземпляры интерфейса

Как только класс Java реализует интерфейс Java, вы можете использовать экземпляр этого класса в качестве экземпляра. Вот пример:

MyInterface myInterface = new MyInterfaceImpl(); myInterface.sayHello();

Обратите внимание, как объявлена переменная типа интерфейса MyInterface, в то время как созданный объект имеет тип MyInterfaceImpl. Java позволяет это, потому что класс MyInterfaceImpl реализует MyInterface. Затем вы можете ссылаться на экземпляры класса MyInterfaceImpl как на экземпляры MyInterface.

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

Реализация нескольких интерфейсов

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

public class MyInterfaceImpl implements MyInterface, MyOtherInterface < public void sayHello() < System.out.println("Hello"); >public void sayGoodbye() < System.out.println("Goodbye"); >>

Этот класс реализует два, называемых MyInterface и MyOtherInterface. Вы перечисляете имена для реализации после ключевого слова Implements, разделенных запятой.

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

import com.jenkov.package1.MyInterface; import com.jenkov.package2.MyOtherInterface; public class MyInterfaceImpl implements MyInterface, MyOtherInterface

реализованные классом выше:

public interface MyInterface
public interface MyOtherInterface

Как видите, каждый интерфейс содержит один метод. Эти методы реализуются классом MyInterfaceImpl.

Перекрывающиеся подписи метода

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

Спецификация не дает никакого решения этой проблемы. Вам решать, что делать в этой ситуации.

Какие типы Java могут реализовывать интерфейсы?

Следующие типы могут реализовывать интерфейсы:

  • Класс;
  • абстрактный класс;
  • Вложенный класс;
  • Java Enum;
  • Динамический Прокси

Переменные интерфейса

Интерфейс может содержать как переменные, так и константы. Однако часто не имеет смысла помещать переменные. В некоторых случаях может иметь смысл определять константы.

Особенно, если эти константы должны использоваться классами, например, в вычислениях, или в качестве параметров для некоторых методов. Я советую вам избегать размещения переменных.

Все переменные в интерфейсе являются открытыми, даже если вы опустите ключевое слово public в объявлении переменной.

Методы интерфейса

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

Все методы являются открытыми, даже если вы опустите ключевое слово public в объявлении метода.

Методы интерфейса по умолчанию

До Java 8 интерфейсы не могли содержать реализацию методов, а содержали только сигнатуры методов. Однако это приводит к некоторым проблемам, когда API необходимо добавить метод.

Если API просто добавляет метод, все классы, которые реализуют интерфейс, должны реализовать этот новый метод. Это хорошо, если все реализующие классы расположены в API. Но если некоторые реализующие классы находятся в клиентском коде API(код, который использует API), то этот код нарушается.

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

public interface ResourceLoader

Теперь представьте, что проект использует этот API и реализовал ResourceLoader следующим образом:

public class FileLoader implements ResourceLoader < public Resource load(String resourcePath) < // in here is the implementation + // a return statement. >>

Если разработчик API хочет добавить еще один метод в ResourceLoader, то класс FileLoader будет нарушен при обновлении этого проекта до новой версии API.

Чтобы облегчить эту проблему, Java 8 добавила концепцию. Метод интерфейса по умолчанию может содержать реализацию этого метода по умолчанию. Классы, которые реализуют интерфейс, но не содержат реализации по умолчанию, автоматически получат реализацию метода по умолчанию.

Вы помечаете метод как метод по умолчанию, используя ключевое слово. Вот пример:

public interface ResourceLoader < Resource load(String resourcePath); default Resource load(Path resourcePath) < // provide default implementation to load // resource from a Path and return the content // in a Resource object. >>

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

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

Статические методы интерфейса

Статические методы в Java должны иметь реализацию.

public interface MyInterface < public static void print(String text)< System.out.print(text); >>

Вызов статического метода выглядит и работает так же, как вызов статического метода в классе. Вот пример вызова статического метода print() из вышеуказанного MyInterface:

MyInterface.print("Hello static method!");

Статические методы в интерфейсах могут быть полезны, когда у вас есть несколько служебных методов, которые вы хотели бы сделать доступными. Например, Vehicle может иметь статический метод printVehicle(Vehicle v).

Интерфейсы и наследование

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

public interface MySuperInterface
public interface MySubInterface extends MySuperInterface

MySubInterface расширяет MySuperInterface. Это означает, что MySubInterface наследует все поля и методы от MySuperInterface. Это означает, что если класс реализует MySubInterface, этот класс должен реализовать все методы, определенные как в MySubInterface, так и в MySuperInterface.

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

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

Вот пример интерфейса Java, который наследуется от нескольких интерфейсов:

public interface MySubInterface extends SuperInterface1, SuperInterface2

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

Наследование и методы по умолчанию

Методы интерфейса по умолчанию немного усложняют правила наследования интерфейса. Хотя обычно класс может реализовать несколько интерфейсов, даже если интерфейсы содержат методы с одинаковой сигнатурой, это невозможно, если один или несколько из этих методов являются методами по умолчанию. Другими словами, если два интерфейса содержат одну и ту же сигнатуру метода(имя + параметры) и один из интерфейсов объявляет этот метод как метод по умолчанию, класс не может автоматически реализовать оба интерфейса.

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

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

Интерфейсы и полиморфизм

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

Посмотрите на эту простую диаграмму классов:

Two parallel class hierarchies used in the same application.

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

Теперь представьте, что вам нужно иметь возможность хранить эти объекты в базе данных, а также сериализовать их в XML, JSON или другие форматы. Вы хотите, чтобы это было реализовано с использованием одного метода для каждой операции, доступного для каждого объекта Car, Truck или Vehicle. Метод store(), метод serializeToXML() и метод serializeToJSON().

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

Где в приведенной выше схеме вы бы поместили эти три метода, чтобы они были доступны для всех классов?

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

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

public interface Storable
public interface Serializable

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

Car car = new Car(); Storable storable =(Storable) car; storable.store(); Serializable serializable =(Serializable) car; serializable.serializeToXML(new FileWriter("car.xml")); serializable.serializeToJSON(new FileWriter("car.json"));

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

Универсальные интерфейсы

public interface MyProducer()

Этот интерфейс представляет интерфейс, который содержит единственный метод, который называется производством(), который может произвести единственный объект. Так как возвращаемое значение yield() – Object, он может возвращать любой объект Java.

public class CarProducer implements MyProducer < public Object produce() < return new Car(); >>
MyProducer carProducer = new CarProducer(); Car car =(Car) carProducer.produce();

public interface MyProducer

public class CarProducer implements MyProducer < @Override public T produce() < return(T) new Car(); >>
MyProducer myCarProducer = new CarProducer(); Car produce = myCarProducer.produce();

Как вы можете видеть, поскольку универсальный тип для экземпляра CarProducer установлен на Car, больше нет необходимости приводить объект, возвращенный из метода yield(), поскольку в объявлении исходного метода в интерфейсе MyProducer указано, что этот метод возвращает тот же тип, который указан в универсальном типе при использовании.

MyProducer myStringProducer = new CarProducer(); String produce1 = myStringProducer.produce();
public class CarProducer implements MyProducer < @Override public Car produce() < return new Car(); >>
MyProducer myCarProducer = new CarProducer(); Car produce = myCarProducer.produce();

Как вы можете видеть, по-прежнему нет необходимости приводить объект, возвращаемый функциейручки(), поскольку реализация CarProducer объявляет, что это экземпляр Car.

Обобщения Java более подробно описаны в моем руководстве по обобщению Java.

Функциональные интерфейсы

С Java 8 была введена новая концепция, называемая функциональными интерфейсами. Короче говоря, функциональный интерфейс – это интерфейс с единственным нереализованным методом(нестандартный, нестатический метод). Я объяснил функциональные интерфейсы в моем учебнике по функциональному интерфейсу Java, который является частью моего учебника по функциональному программированию на Java. ,

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *