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

Методология интерфейсов Java: должен ли каждый класс реализовывать интерфейс?

Я программировал на Java для нескольких курсов в университете, и у меня есть следующий вопрос:

Насколько методологически принято, чтобы каждый класс реализовал интерфейс? Является ли это плохой практикой, чтобы не делать этого? Можете ли вы описать ситуацию, когда не рекомендуется использовать интерфейсы?

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

4b9b3361

Ответ 1

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

Обычно вам нужен интерфейс, когда:

  • Ваша программа предоставит несколько реализаций для вашего компонента. Например, реализация по умолчанию, являющаяся частью вашего кода, и макетная реализация, которая используется в тесте JUnit. Некоторые инструменты автоматизируют создание макетной реализации, например, EasyMock.
  • Вы хотите использовать инъекцию зависимостей для этого класса с каркасом, таким как Spring или JBoss Micro-Container. В этом случае рекомендуется указывать зависимости одного класса с другими классами с помощью интерфейса.

Ответ 2

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

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

Ответ 3

Каждый класс реализует интерфейс (т.е. контракт), поскольку он предоставляет не-частный API. Независимо от того, следует ли вам представлять интерфейс отдельно, поскольку интерфейс Java зависит от того, является ли реализация "понятием, которое меняется".

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

Некоторые люди будут кричать "YAGNI", предполагая, что у вас есть полный контроль над изменением кода, если вы обнаружите новое требование позже. Другие люди будут справедливо бояться, что им нужно будет изменить неизменяемый - опубликованный API.

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

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

В некоторых языках (например, С++, С#, но не Java) вы можете получить преимущество в производительности, если ваш класс не содержит виртуальных методов.

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

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

Ответ 4

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

Если у вашей программы нет необходимости иметь более 1 реализации для данного класса, тогда вам не нужен интерфейс. Например, в простой шахматной программе, которую я написал, мне нужен только один тип объекта Board. Шахматная доска - шахматная доска - шахматная доска. Создание интерфейса Board и его реализация потребовали бы большего количества кода для написания и поддержки.

Так легко переключиться на интерфейс, если он вам в конечном итоге понадобится.

Ответ 5

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

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

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

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

Ответ 6

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

Ответ 7

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

Ответ 8

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

  • Чисто функциональные объекты, возможно, не нужно (например, Pattern, CharMatcher - хотя последний реализует предикат, он является вторичным по отношению к его основной функции)
  • Чистые держатели данных, вероятно, не нужны к (например, LogRecord, Locale)
  • Если вы можете представить себе другую реализацию данной функции (например, в памяти Кэш-кэш на основе диска), попробуйте изолировать функциональность в интерфейсе. Но не заходите слишком далеко, пытаясь предсказать будущее.
  • Для целей тестирования это очень удобно, когда классы, которые делают Входы/выходы или начальные потоки легко макетируются, поэтому что пользователи не платят штраф, если выполняющих свои тесты.
  • Там ничего хуже, чем интерфейс, который основной реализации. Обратите внимание, где вы рисуете линию и убедитесь, что ваш интерфейс Javadoc нейтрален таким образом. Если это не так, вам, вероятно, не нужен интерфейс.
  • В общем говоря, предпочтительнее классы, предназначенные для общественного потребления вне вашего пакета/проекта, чтобы реализуйте интерфейсы, чтобы пользователи менее связаны с вашим реализация du jour.

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

Ответ 9

Хороший способ узнать, что считается хорошей методологией, особенно когда речь заходит о дизайне структуры кода, - это смотреть на свободно доступный код. С Java очевидным примером является просмотр системных библиотек JDK.

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

Ответ 10

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

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

Ответ 11

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

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

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

Ответ 12

Интерфейс подобен контракту между поставщиком услуг (сервером) и пользователем такой службы (клиента).

  • Если мы разрабатываем Web-сервис, и мы разоблачаем остальные маршруты через классы контроллеров, классы контроллеров могут реализовывать интерфейсы и эти интерфейсы действуют как соглашение между веб-службой и другие приложения, которые используют эту веб-службу.
  • Интерфейсы Java, такие как Serializable, Clonnable и Удаленный используется для указания на компилятор или JVM. Когда JVM видит класс которые реализуют эти интерфейсы, он выполняет некоторую операцию на поддержка Сериализация, клонирование или вызов удаленного метода. Если ваш класс нуждается в этих функциях, вам придется реализовать эти интерфейсы.

Ответ 13

Использование интерфейса вот-вот изменит вашу инфраструктуру приложения. Поскольку, как я уже упоминал здесь (Multiple Inheritance Debates II: согласно Stroustrup), множественное наследование было отменено в java и С#, о которых я сожалею, всегда нужно использовать интерфейс, потому что вы никогда не знаете что будет в будущем.