абстрактные классы и интерфейсы лучшие практики в Java - PullRequest
4 голосов
/ 19 декабря 2009

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

Так какая же здесь лучшая практика? Я говорю о таких вопросах, как:

1) Должен ли абстрактный класс реализовывать интерфейс или его дочерние классы? Должен ли каждый класс? Мне кажется, что просто абстрактный класс должен. Конечно, все классы могут реализовывать интерфейс, но это кажется излишним, потому что потомки абстрактного «наследуют» интерфейс, потому что они расширяют абстрактный класс.

2) Учитывая, что абстрактный класс реализует части интерфейса, должен ли он также объявлять абстрактные методы для методов, которые он не реализует? Мне кажется, что это правильно, но в некотором смысле это кажется излишним, потому что потомки абстрактного должны будут реализовать эти методы для компиляции.

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

Ответы [ 5 ]

9 голосов
/ 19 декабря 2009

Принцип, который должен вам здесь помочь. СУХОЙ: не повторяйте себя (http://en.wikipedia.org/wiki/Don%27t_repeat_yourself).

В этом контексте СУХОЙ означает, что вы не должны выполнять ненужную работу.

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

Что касается второго вопроса, нет смысла повторять методы интерфейса в абстрактном классе, который его реализует. Это избыточная работа. Более того, когда интерфейс развивается / изменяется, вам нужно будет изменить методы-аналоги (абстрактные) в абстрактном классе, который является головной болью. В какой-то момент вы пропустите обновление некоторых методов, и конкретный класс должен будет реализовать их напрасно.

2 голосов
/ 19 декабря 2009

Самый гибкий способ программирования для этого:

  1. Предоставить интерфейс
  2. Укажите абстрактный класс, который реализует интерфейс
  3. Укажите конкретные классы, которые либо выходят из абстрактного класса, либо расширяются из другого класса, и реализуют интерфейс
  4. Всегда (если вы не можете) объявлять переменные / параметры / константы как интерфейс, а не абстрактный класс или конкретные классы

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

Выполняя # 4, вы гарантируете, что все классы, которые реализуют интерфейс, могут использоваться - если вместо этого вы используете абстрактный класс, то классы, которые реализуют интерфейс, но не расширяют абстрактный класс, не могут использоваться.

(более поздняя часть)

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

2 голосов
/ 19 декабря 2009

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

1 голос
/ 19 декабря 2009

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

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

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

0 голосов
/ 19 декабря 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...