Что более уместно:геттеры и сеттеры или функции?

StackOverflow https://stackoverflow.com/questions/175228

Вопрос

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

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


public class SomeClass {
private:
    bool mIsVisible;

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

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


bool getVisible() { return mIsVisible; };

void setvisible (bool visible) {if (! ошибочно && visible) {draw ();} else if (неправильно &&! visible) {eRase ();}

mIsVisible = visible;

}

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


bool isVisible() { return mIsVisible; };

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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

Я бы выбрал набор isVisible()/show()/hide().

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

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

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

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

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

Я предпочитаю методы show() и скрыть(), потому что они явно сообщают, что вы собираетесь делать.setVisible(boolean) не сообщает вам, будет ли метод отображаться/отрисовываться сразу.Плюс show() иide() — более удачные методы для интерфейса (ИМХО).

Неявно перечисленные вами функции «показать» и «скрыть» являются установщиками.

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

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

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

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

w.showIfAndOnlyIf(shouldBeShowingAccordingToBusinessLogic())

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top