Подтвердить что ты не робот

Когда следует использовать интерфейс в java?

Хорошим примером того, когда именно использовать интерфейсы, особенно в Java, были бы идеальными и любые конкретные правила, которые применяются.

4b9b3361

Ответ 1

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

JDBC API - отличный пример. Он существует почти из всех интерфейсов. Конкретные реализации предоставляются как "драйверы JDBC". Это позволяет вам написать весь код JDBC независимо от поставщика базы данных (DB). Вы можете просто изменить драйвер JDBC, не изменяя ни одной строки кода Java (за исключением любого жестко закодированного SQL-кода SQL), когда вы хотите переключить поставщика БД.

Другим примером является Java EE API, он также содержит довольно много интерфейсов и абстрактных классов. Конкретные реализации предоставляются как "серверы приложений Java EE", "Servletcontainers" и т.д., Такие как Sun Glassfish, Apache Tomcat и т.д. Это позволяет развернуть веб-приложение (WAR) на любой веб-сервер Java, который вам нравится.

Ответ 2

Хорошим местом для просмотра будет сборка.

java.util.List //interface

java.util.ArrayList //Concrete class
java.util.LinkedList //Concrete class

Итак, вы можете написать такой код:

List l = new ArrayList();

l.add(..)
//do something else.

Если в будущем вы захотите изменить реализацию, скажем LinkedList или вы владеете интерфейсом AwesomeList which implements List, все, что вам нужно сделать, это изменить самую первую строку:

List l = new MyAwesomeList();
or
List l = new LinkedList();

Остальная часть кода будет проходить через.

Ответ 3

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

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

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

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

Одним из важных правил, которые следует помнить для безопасного использования, является Принцип замены Лискова UncleBob, Wikipedia]. Хотя компилятор на языке Java должен убедиться, что синтаксически все в порядке (правильное количество параметров, типов,...), LSP имеет дело с семантикой. Короче говоря, LSP говорит, что каждая реализация интерфейса должна (и) вести себя правильно, чтобы быть поистине подменяемой, как описано выше.

Ответ 4

Из документации oracle страница

Рассмотрим использование интерфейсов, если:

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

Посмотрите на связанные вопросы SE с примерами кода, которые уже имеют хорошие ответы.

Есть ли больше для интерфейса, чем правильные методы

В чем разница между интерфейсом и абстрактным классом?

Как я должен объяснить разницу между интерфейсом и абстрактным классом?

Ответ 5

Посмотрите учебник по сборке JDK на текст ссылки. Подумайте о коллекциях. Что приходит на ум? Его можно заказать или его нельзя заказать, и он может иметь дубликаты или нет.

So Collection - это интерфейс со списком (упорядоченный) и Set (неупорядоченный) в качестве вспомогательных интерфейсов. Теперь есть много вопросов со списками, если они должны быть синхронизированы/или нет, если это связанный список или нет. Каждое "поведение" будет иметь свои собственные интерфейсы/абстрактные классы.

Абстрактные классы необходимы, если вы хотите указать "некоторое" поведение в коллекциях. Например, все коллекции (sets/lists и т.д.) Могут иметь представление "toString", которое просто перебирает элементы (упорядоченные или нет) и строит их. Это поведение может присутствовать в "AbstractCollection" и т.д.

Если вы следуете иерархии коллекций JDK, это отличное место для изучения интерфейсов и абстрактных классов:)

Ответ 7

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

public interface Xmlizable
{
    public String toXML();
}

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

Ответ 8

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

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

Тогда мы имеем AbstractList: абстрактный класс, реализующий List, который обеспечивает реализацию почти всего, что требуется полноценным List - для создания вашей собственной реализации List, все, что вам нужно сделать, это расширить AbstractList и заполните несколько методов. Это яркий пример того, когда абстрактный класс является хорошим выбором - когда вы хотите обеспечить почти полную реализацию чего-либо, в котором не хватает нескольких пробелов, которые должны быть заполнены клиентским кодом.

Подсказка: Если вы создаете абстрактный класс, содержащий только абстрактные методы, вы должны, вероятно, создать его интерфейс.

Ответ 9

Этот ответ по существу тот же самый, что и coolest_head, только немного более явным образом передавая полезность.

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

В качестве примера предположим, что вы хотите читать произвольные данные и печатать их так:

SomeReader someReader = new SomeReader();
String data = someReader.readLine();
System.out.println(data);

Ничего особенного здесь, не так ли? Но, хотя этот пример прост, он уже привязан к классу SomeReader, что означает, что все изменения, внесенные вами в этот класс, должны быть распространены в класс, в котором вы используете класс, особенно если вы реорганизуете некоторые внутренние части! Вместо этого вы хотите сделать это

IMyReader reader = new SomeReader();
System.out.println(reader.readLine());

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

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

public class RowPrinter {

    private final IMyReader reader;

    public RowPrinter(IMyReader reader) {
        this.reader = reader;
    }

    public void print() {
        IMyReader reader = getReader();
        System.out.println(reader.readLine());
    }

    protected IMyReader getReader() {
        return reader;
    }
}

Обратите внимание, что часть с конструктором? Это инверсия управления и позвольте мне просто сказать вам, что здесь есть крутая часть программного обеспечения. Я могу говорить по своему опыту, это помогает вам с большим количеством хлопот, будь то переход от продукта базы данных к другому или обеспечение определенных частей кода. Или, может быть, вы просто хотите добавить слой ведения журнала в какой-то класс, легко выполнимый с помощью wrap decorator, который происходит для реализации того же интерфейса как завернутый класс. И это только начало.

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

Ответ 10

Основным принципом ООП является скрытие информации: скрыть детали реализации и показать только описание основных услуг вызывающему.

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

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

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

Ответ 11

Интерфейсы в удаленной связи:

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

Боковое примечание:

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

Ответ 12

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

Я также рекомендовал бы использовать интерфейсные бэкэнды для всех классов в отношениях наследования, по крайней мере, в более серьезных проектах: к сожалению, у меня больше нет ссылки, но разработчик языка Java однажды сказал, что включение Class-Inheritance было Самая большая ошибка при разработке языка.

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