Дженерики против Интерфейсов - PullRequest
9 голосов
/ 25 февраля 2010

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

Хотя я все еще пытаюсь овладеть Generics, мой вопрос - это правильный подход к дизайну? Интерфейсы делают ваш дизайн более гибким / отделенным. Принимая во внимание, что Generics, реализует безопасность типов и заставляет вас передавать определенный тип класса. Не очень помогает в развязке вашего кода. Это правильно?

Один пример -

public MyWizard extends SignupWizard<SignupSection, SignupObject, SignupListener, SignupView>{
}

вместо этого дизайн был бы более гибким, если бы он был ..

public interface Wizardable{
  public SignableSection getSection();
  public SignableObject getSignableObject();
...
}

public MyWizard implements Wizardable{
....
}

Ответы [ 5 ]

4 голосов
/ 03 марта 2010

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

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

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

Как я уже упоминал в комментарии, любые подклассы будут устанавливать параметры этого типа и ничего не предоставлять пользователю. Таким образом, у вас может быть что-то вроде class MegaSignupWizard extends SignupWizard<MegaSignupSection, MegaSignupObject, MegaSignupListener, MegaSignupView>, и все остается совершенно корректным с MegaSignupWizard, имеющим доступ к специализированным методам в классах без необходимости приведения. Теперь это круто:)

3 голосов
/ 25 февраля 2010

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

1 голос
/ 17 сентября 2010

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

1 голос
/ 25 февраля 2010

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

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

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

0 голосов
/ 25 февраля 2010

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

Я не уверен, что ваше вышеупомянутое использование выглядит хорошо. Если вы расширяете объект или реализуете интерфейс, вам не нужно передавать такие объекты. Обобщения используются для реализации класса с абстрактным типом, например, коллекции, которая может действовать на что угодно. Что произойдет, если я пройду SignupWizard<int, int, int, int>, что совершенно верно?

Для этой конкретной идеи, возможно, вы хотите использовать интерфейсы. Имейте интерфейс, определяющий действие мастера, каждый объект, реализующий его, и mywizard, способный к .addaction (int position, действие wizardaction). На самом деле это определенно проблема интерфейсов.

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

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