Рекомендации по использованию интерфейса Java - Являются ли геттеры и сеттеры в интерфейсе плохими? - PullRequest
35 голосов
/ 15 июля 2009

Что люди думают о лучших рекомендациях для интерфейса? Что должно и не должно входить в интерфейс?

Я слышал, как люди говорят, что, как правило, интерфейс должен определять только поведение, а не состояние. Означает ли это, что интерфейс не должен содержать геттеры и сеттеры?

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

Ответы [ 11 ]

24 голосов
/ 15 июля 2009

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

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

РЕДАКТИРОВАТЬ: комментарии предполагают, что геттеры и сеттеры подразумевают, что простое поле используется для резервного хранения. Я категорически не согласен с этим подтекстом. На мой взгляд, подразумевается, что получить / установить значение «достаточно дешево», но не то, что оно хранится как поле с тривиальной реализацией.


РЕДАКТИРОВАТЬ: Как отмечено в комментариях, это явным образом указано в спецификации JavaBeans раздел 7.1:

Таким образом, даже когда автор сценария печатает в чем-то вроде b.Label = foo есть еще вызов метода в целевой объект для установки свойства, и целевой объект имеет полный программное управление.

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


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

Например, рассмотрим компонент с

getWidth()
getHeight()
getSize()

Верите ли вы, что существует три переменных? Разве не разумно иметь:

private int width;
private int height;

public int getWidth() {
    return width;
}

public int getHeight() {
    return height;
}

public Size getSize() {
    return new Size(width, height); // Assuming an immutable Size type
}

или (предпочтительно ИМО):

private Size size;

public int getWidth() {
    return size.getWidth();
}

public int getHeight() {
    return size.getHeight();
}

public Size getSize() {
    return size;
}

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

12 голосов
/ 15 июля 2009

Я думаю, что в общем случае объявлены два типа интерфейсов:

  1. a описание услуги . Это может быть что-то вроде CalculationService. Я не думаю, что методы getX должны быть в таком интерфейсе, а , конечно, , а не setX. Они довольно явно подразумевают детали реализации, что не является задачей интерфейса такого типа.
  2. a модель данных - существует исключительно для абстрагирования реализации объектов данных в системе. Они могут быть использованы для помощи в тестировании или просто потому, что некоторые люди, такие же старые, как я, помнят времена, когда (например) использование персистентной среды связывало вас с определенным суперклассом (то есть вы решили реализовать интерфейс в случае, если вы переключились ваш постоянный слой). Я думаю, что наличие методов JavaBean в интерфейсе этого типа вполне разумно.

Примечание: классы коллекций, вероятно, соответствуют типу # 2

10 голосов
/ 15 июля 2009

Нет ничего плохого в добытчиках / сеттерах. Тем не менее:

  1. Я склонен делать свои объекты неизменяемыми (в первую очередь) относительно полей, которые они содержат. Зачем ? Я создаю большинство вещей на этапе строительства. Если я хочу что-то изменить позже, я ослабляю эти ограничения. Поэтому мои интерфейсы будут содержать геттеры, но не сеттеры (есть и другие преимущества, в частности, многопоточность).
  2. Я хочу, чтобы мои объекты делали что-то для меня , а не наоборот. Поэтому, когда один из моих объектов получает несколько геттеров, я начинаю спрашивать, должен ли этот объект обладать большей функциональностью, а не выставлять все свои данные для чего-то еще, с чем можно работать. См. этот ответ для более подробной информации.

Это все руководящие указания, примечание.

4 голосов
/ 15 июля 2009

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

Я бы не сказал, что у вас не должно быть геттеров в интерфейсе. Имеет смысл иметь интерфейс ReadableDataThingie, который реализуется DataThingieBean.

2 голосов
/ 04 апреля 2010

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

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

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

Учитывая это, нет ничего плохого - синтаксически и семантически - в том, что в интерфейсах есть сеттеры и геттеры.

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

Теперь, если мы рассмотрим методы получения и установки с точки зрения реализации классов, совместимых со спецификациями JavaBeans, вам не нужно определять интерфейсы для них.

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

Надеюсь, это поможет.

1 голос
/ 15 июля 2009

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

1 голос
/ 15 июля 2009

Это затрагивает всю тему «Геттер / Сеттерс» - злая тема, которая неоднократно обсуждается на этом сайте и в других местах.

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

0 голосов
/ 16 августа 2009

Геттеры используются для запроса состояния объекта - чего вы действительно можете избежать при разработке вашего интерфейса. Читать http://www.pragprog.com/articles/tell-dont-ask

0 голосов
/ 15 июля 2009

В основном, если ответ на вопрос «Нужно ли мне знать значение [state, property, whatThignAMaGit] для работы с его экземпляром?» тогда да ... средства доступа принадлежат интерфейсу.

List.size () от Джона выше - прекрасный пример геттера, который должен быть определен в интерфейсе

0 голосов
/ 15 июля 2009

Я использовал такие интерфейсы, например, у нас были классы с полями beginDate, endDate. Эти поля были во многих классах, и у меня был один вариант использования, мне нужно было получить эти даты для разных объектов, поэтому я извлек интерфейс и был очень счастлив

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