В чем суть интерфейсов в программировании?

Не совсем ясно, для чего именно предназначены интерфейсы. Зачем мне в одном месте описывать методы, а в другом реализовывать? Зачем именно нужно дополнительное место для описания, если я могу это сделать сразу в классе? Или же это сделано для удобства восприятия кода? Например, если вижу, что класс наследуется от интерфейса, то знаю, каким функционалом он обладает? Если да, то почему бы не придумать имя класса, из которого будет ясна функциональность? Что первично - интерфейс, или класс? По возможности, приведите примеры кода(желательно не из объектной области, желательно на Java), где будет показано, что в данной ситуации необходимо использовать интерфейс, или что его использование удобнее, чем не использование. В книгах везде приводят примеры того, что может делать интерфейс, но в примерах из книги я не вижу крайней необходимости его использования. Спасибо!
  • Вопрос задан
  • 54300 просмотров
Решения вопроса 1
@ZzZero
Я делаю систему контроля яркости.
Я хочу настраивать яркость всего (гирлянды, люстры, фонарика, экрана телефона).
В коде выглядит примерно так
class BrightControl
   public void setDefaultBright(Object obj){
         obj.setBright(10);
   }
}

Метод setDefaultBright принимает любой объект. Ведь мне всё равно яркость чего настраивать.
Мой код используют другие разработчики, я не могу контролировать их.
Как мне убедиться, что у объекта, который мне пришел в качестве аргумента, есть метод setBright?
Я пишу интерфейс, и говорю, что метод setDefaultBright принимает только объекты, которые реализуют этот интерфейс.

Если кроме меня самого никто не будет использовать эту систему контроля яркости. То я просто буду держать у себя в голове, что в метод setDefaultBright можно отправлять только объекты, у которых есть метод setBright, но поддержка кода усложняется, через год и не вспомнишь...
Ответ написан
Пригласить эксперта
Ответы на вопрос 8
ptchol
@ptchol
Linux system administrator
Интерфейс это фактически регламент взаимодействия.
Класс который реализует интерфейс обязан реализовывать все его методы.
В интерфейсе вы описываете лишь сигнатуры методов, то есть вы указываете что класс наследник должен уметь делать, но как он будет это делать, тот решает сам.
Таким образом вы уверенны, что если класс реализует тот или иной интерфейс, все объекты данного класса имеют определенный набор методов.
ООП - мир абстракций :) Впустите его в себя :) Интерфейсы это еше одна абстракция позволяющая отделить описание от реалзиации.

"Придумать класс с правильным именем" - так вы не сможете заставить "наследников" реализовывать функционал.

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

interface Instruments {
    final static String key = "До мажор";
    public void play();
}
class Drum implements Instruments {
    public void play() {
        System.out.println("бум бац бац бум бац бац");
    }
}
class Guitar implements Instruments {
    public void play() {
        System.out.println("до ми соль до ре до");
    }
}


p.s: программисты дополнят и поправят.
Ответ написан
rEAcT1oNmanT1s
@rEAcT1oNmanT1s
Да, это сделано именно для восприятия человеком кода. Легкие программы, где не особо много строк кода, не сильно сложны для восприятия человека, а программы которые имеют тысячи строк кода, уже соответственно нужно разделять на файлы в одних файлах лежат условия "что нужно сделать?", а в других "как это сделать?".

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

Если программа огромная и вы об это знаете заранее, то её стоит разбить заранее на модули. Зачем или почему? Первая причина это воспринимаемость кода человеком, о котором уже шла речь, а второе будет намного легче найти ошибки в исходном коде, который вы будете писать и они будут.

P.S. Даже когда пишите что-то или задаете вопросы, можете разделять на блоки текста, как написал я, так воспринимается легче чем то, что написано в куче , не правда ли?
Ответ написан
Комментировать
leventov
@leventov
ООП#Основные понятия

Без интерфейса (как концепции) немыслимы три из четырех основных понятий ООП.

Конкретно в Java интерфейсы как отдельные сущности нужны, потому что нет множественного наследования. В C++ и многих других языках с поддержкой множественного наследования интерфейсов как отдельной сущности нет (чисто виртуальный класс - частный случай обычного абстрактного класса).
Ответ написан
Комментировать
Foror
@Foror
Графоман
Для начала нужно сразу понять, что интерфейс это частный случай класса. Но в Java оно имеет отдельное ключевое слово, а в C++ это просто класс без реализации. Поэтому интерфейс просто задает некий стандарт для работы с кучей разнообразных реализаций.

Например, интерфейс Iterable говорит, что классы реализующие данный интерфейс имеют элементы и их можно перебирать в цикле вызывая метод next(). А значит, если создаете какой-то контейнер или коллекцию, то можно реализовать Iterable. Не выдумывая свои методы для работы с контейнером. Тем самым появляется некий общий стандарт - интерфейс для работы с контейнерами.

А если вы делаете игру, то можете создать интерфейс Unit, тем самым задав классам определенное поведение. Например, unit должен обязательно иметь метод atack(), isDead() и т.д.

А дальше, в цикле делаете проверку всех юнитов:
loop(...) {
if (unit.isDead())
removeFromMap(unit);
}

Ну и конечно Unit может быть и просто классом или абстрактным классом, в котором реализованы atack и isDead, а может быть только isDead, потому что attack у каждого типа юнита индивидуально и требует собственной реализации. Т.е. приходим к тому, что интерфейс это также частный случай абстрактного класса.

Т.е. тут уже вступает в действие полиформизм, т.е. интерфейсы по сути дают полиформизм. Ну, а в Java они еще позволяют делать множественное наследование или другими словами задать классу несколько свойств поведения, например Unit может быть также и Iterable, тем самым можно дать юнитам инвентарь и перебирать элементы в нем.

И соответсвенно если Unit у вас будет классом или абстрактным классом, то унаследовав Unit в Java, вы просто не сможете дать наследнику еще и Iterable поведение, если Iterable будет тоже классом.

OrcWarrior implements Unit, Iterable - так можно

OrcWarrior extends Unit, Iterable - так в Java нельзя, но можно в С++, а Unit и Iterable тогда всегда будут объявляться как class...

Из-за этого, в Java приветствуется не наследование, а композиция. Т.е. нафига каждый раз реализовывать Unit.isDead, если он стандартный? Поэтому, создается скажем класс UnitAI и делается следующее:

class OrcWarrior implements Unit, Iterable {
UnitAI ai;

UnitAI getAI(){
return ai;
}
}

class UnitAI {

boolean isDead() {
....
}
}

interface Unit {
void attack();
UnitAI getAI();
}

Вот это называется композиция, т.е. в OrcWarrior, HumanWarrior вы подмешиваете UnitAI, в котором уже реализовано isDead, и тем самым не нужно каждый раз его реализовывать одним и тем же кодом. В С++ такого можно не делать, там есть поддержка множественного наследование, но оно имеет свои минусы. Впрочем, как и композиция имеет плюсы/минусы.
Ответ написан
Комментировать
Интерфейс - это штука, которая делает возможным, очень эффективное "общение" разработчиков. Особенно в больших проектах с огромным числом разработчиков. Тебе не нужно бегать и объяснять каждому из сотни человек, как использовать твой класс. Продумываешь хороший и понятный интерфейс - а они его используют. Можно вообще из компании уйти, а интерфейс будет жить и использоваться.

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

В общем, воспринимайте интерфейс как самый эффективный инструмент общения разработчиков в команде.
Ответ написан
Комментировать
Quber
@Quber
PHP Team lead
@syntax Буду короток. Вы всё правильно понимаете. Вы можете описать интерфейс в классе, однако считается что с интерфейсом удобнее. Плюсы приведены в других комментариях. Однако если нет необходимости, можете не писать интерфейсы, это дело каждого.
Ответ написан
Комментировать
svd71
@svd71
Классы позволяют проводить раширение дочерних элементов только в функционале классов. Интерфейся позволяют также раширять функциональность, но для любых классов. В этом то и главное отличие: Классы можно раширять "вертикально" (каждый потомок может расширить класс), итерфейсы позволяют раширять классы "горизонтально"(интерфейс можно имплементировать в любом классе, даже не имеющими общие предков).
Ответ написан
Комментировать
pazukdev
@pazukdev
Java Dev
1. Класс - это всегда интерфейс + реализация (хотя бы частичная).
2. Интерфейс - это способ полностью отделить интерфейс от реализаци. Т.е. полностью абстрактный класс. Служит для описания котракта поведения класса для взаимодействия с внешним окружением.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Bell Integrator Ульяновск
До 400 000 ₽
Bell Integrator Хабаровск
До 400 000 ₽
Bell Integrator Ижевск
До 400 000 ₽
19 апр. 2024, в 23:00
5000 руб./за проект
19 апр. 2024, в 20:43
20000 руб./за проект