Что более уместно: геттеры и сеттеры или функции? - PullRequest
7 голосов
/ 06 октября 2008

Всегда ли целесообразно отказаться от шаблонов getMyValue () и setMyValue () для методов получения и установки, если альтернативные имена функций делают API более очевидным?

Например, представьте, что у меня есть этот класс в C ++:


public class SomeClass {
private:
    bool mIsVisible;

public:
    void draw();
    void erase();
}

Я мог бы добавить функции, чтобы получить / установить «mIsVisible» следующим образом:


bool getVisible() { return mIsVisible; };</p>

<p>void setVisible(bool visible) { 
    if (!mIsVisible && visible) {
        draw();
    } else if (mIsVisible && !visible) {
        erase();
    }</p>

<pre><code>mIsVisible = visible;

}

Однако было бы одинаково возможно использовать вместо этого следующие методы:


bool isVisible() { return mIsVisible; };

void show() { 
    if (!mIsVisible) {
        mIsVisible = true;
        draw();
    }
}

void hide() {
    if (mIsVisible) {
        mIsVisible = false;
        erase();
    }
}

Короче говоря, лучше ли иметь один метод "setVisible (bool)" или пару методов "show ()" и "hide ()"? Есть соглашение или это чисто субъективная вещь?

Ответы [ 10 ]

13 голосов
/ 06 октября 2008

Прочтите статью " Скажите, не спрашивайте " на веб-сайте Pragmatic Programmers, и я думаю, вы увидите, что второй пример - это путь.

По сути, вы не должны распространять логику через ваш код, который подразумевается в вашем первом примере, а именно:

  1. получить текущее значение видимости,
  2. принять решение на основе стоимости,
  3. обновить объект.
5 голосов
/ 06 октября 2008

В приведенном вами примере show() и hide() имеют большой смысл, по крайней мере для меня.

С другой стороны, если у вас есть свойство skinPigment и вы решили создать функции с именами tanMe() и makeAlbino(), это будет очень плохой, неочевидный выбор.

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

3 голосов
/ 06 октября 2008

сеттеры на самом деле имеют мало общего с ориентацией объекта, что идиома программирования применяется в примере. добытчики немного лучше, но во многих случаях можно жить без них. Если все можно получить и установить, какой смысл иметь объект? Операции над объектами должны вызываться для выполнения задач, изменение внутреннего состояния является лишь побочным эффектом этого. Плохая вещь о сеттере в присутствии полиморфизма - одного из краеугольных камней ОО - заключается в том, что вы заставляете каждый производный класс иметь сеттер. Что если у рассматриваемого объекта нет необходимости во внутреннем состоянии, называемом mIsVisible? Конечно, он может игнорировать вызов и реализовать его как пустой, но тогда вы останетесь с бессмысленной операцией. OTOH, такие операции, как show и hide, могут быть легко переопределены различными реализациями, не раскрывая ничего о внутреннем состоянии.

3 голосов
/ 06 октября 2008

Я бы пошел с набором isVisible () / show () / hide ().

setVisible () подразумевает, что все, что он делает, это изменяет внутреннюю переменную. show () и hide () проясняют побочные эффекты.

С другой стороны, если все getVisible () / setVisible () сделали равным , чтобы изменить внутреннюю переменную, то вы просто изменились на удивление мало от того, чтобы иметь их в качестве открытых полей.

2 голосов
/ 06 октября 2008

Если переключение mIsVisible действительно сразу включает и выключает видимость объекта, используйте сценарий «показать / скрыть». Если он будет оставаться в старом состоянии немного дольше (например, до тех пор, пока что-то еще не вызовет перерисовку), тогда сценарий set / get будет правильным.

2 голосов
/ 06 октября 2008

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

1 голос
/ 06 октября 2008

Я предпочитаю методы show () и hide (), потому что они явно сообщают, что вы собираетесь делать. SetVisible (boolean) не сообщает вам, будет ли метод показывать / рисовать сразу. Плюс show () и hide () - метод с лучшим именем для интерфейса (IMHO).

0 голосов
/ 06 октября 2008

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

метод setVisible имеет «побочный эффект», который также отображает или скрывает SomeClass. Методы отображения / скрытия лучше передают смысл происходящего.

0 голосов
/ 06 октября 2008

В случае, если вам действительно нужно написать код, подобный

if (shouldBeShowingAccordingToBusinessLogic()) w.show();
else w.hide();

повсюду, вам может быть лучше с

w.showIfAndOnlyIf(shouldBeShowingAccordingToBusinessLogic())

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

w.setPostponedVisibility(shouldBeShowingAccordingToBusinessLogic());
...
w.realizeVisibility();

(Разве я не говорил, что это странно?)

0 голосов
/ 06 октября 2008

Неявно, обе перечисленные вами функции 'show' и 'hide' являются сеттерами

Для логических выражений я бы подумал, что один инструмент, который вы показали, был бы хорош. Однако функции .show и .hide также выглядят как команды, а не функции, которые изменяют состояние объекта.

...