В c++ я новичок и не могу понять, для чего, собственно, нужны геттеры и сеттеры? Почему нельзя просто сделать переменные внутри класса глобальными и изменять непосредственно их? В чем необходимость делать переменную приватной и создавать функции для ее модификации или получения ее значения?
-
1Геттеры и сеттеры позволяют выполнять действия кроме установки/получения значения переменной. Например int a = obj.temperature может инициировать обмен данными с оборудованием, если сделано через геттер. – Владимир Мартьянов Sep 06 '15 at 09:41
-
2Вам тут сейчас много всего расскажут, только учтите, что в реальном программировании (я не беру в расчет разработку разных фреймворков и т.п. оболочек ) эта техника практически не имеет смысла. – avp Sep 06 '15 at 09:48
-
2@avp: как раз таки имеет, надо только уметь ее применять к месту – Kromster Sep 06 '15 at 09:49
-
@KromStern, то ли 99% программеров не умеют, то ли они каждый раз считают ее неуместной в очередной программе (впрочем, возможно, это не относится к виндузовому миру (там я не пишу)) – avp Sep 06 '15 at 09:52
-
Эээ... В C++ появились свойства? – VladD Sep 06 '15 at 10:15
-
@avp: как и 99% статистике в Нете, взято с потолка ) – Kromster Sep 06 '15 at 10:38
-
4Вот аналогичный вопрос по поводу свойств в C#. – VladD Sep 06 '15 at 10:46
5 Answers
Плюсов много и вот некоторые из них:
- можно выборочно давать доступ только к геттеру или только к сеттеру
- предотвращать изменение переменной со стороны (выдавая геттеру ее копию)
- не уверен насчет С, но можно ставить брейкпоинты на методы доступа, чтобы узнать, кто и откуда обратился
- можно добавлять дополнительный код в геттер и сеттер
- при установке значения проверять его валидность (и, например, бросать исключение)
- при установке значения, инициализировать какие-то связанные вещи
- получать геттером значение не из переменной, а вычислять его
- логировать доступ к геттеру/сеттеру
- реализовывать и переопределять поведение геттера/сеттера в дочерних классах
В целом, можно обойтись и без них, но тогда вырастет размер кода, больше времени будет уходить на отладку, компилятор не сможет предостеречь от связанных ошибок. И чем больше/сложнее проект, тем больше пользы они будут приносить.
- 13,809
Главный смысл заключается в том, чтобы отделить реализацию от интерфейса.
Таким образом, с одной стороны, изменения в реализации не влияют на пользовательский интерфейс класса, а, с другой стороны, пользователь класса, имеющий к нему доступ через открытый интерфейс, не сможет нарушить объявленное корректное поведение класса.
В классе могут существовать зависимости между его членами. Поэтому объект класса должен быть осведомлен, когда какой-то член класса подвергся изменению со стороны пользователя, чтобы в соответствии с этим изменением привести в соответствие состояния других членов класса.
Например, если ваш класс температуры содержит два члена данных, температуру по Цельсию и температуру по Фаренгейту, то если пользователь изменил одну из температур, то объект класса должен пересчитать другую температуру, чтобы их значения были согласованы между собой.
Обобщенно это называется одним словом инкапсуляция.
Желая правильно написать это слово - инкапсуляция, - я посмотрел, как оно пишется в словаре, и словарь помимо всего прочего выдал такое пояснение к слову:
Инкапсуляция - иммунная реакция у насекомых в ответ на паразитарную инвазию.
Перефразируя это определение по отношению к классам, можно сказать, что инкапсуляция в ООП - это иммунная реакция класса в ответ на неправильные действия пользователей в отношении его объектов. :)
- 13,809
- 44,824
Пример типичной ошибки
Object obj = new Object();
if(obj.properties = null) return false; // Опечатка, которую трудно отловить
if(obj.getProperties() = null) return false; // не скомпилируется, так как результату функции нельзя присвоить значение
if(obj.getProperties() == null) return false; // Правильный вариант
getProperties() возвращает значение, а в операции присваивания в левой части может участвовать только переменная!
-
1Это какой язык вы используете? Если, например, C#, то второе предложение также не будет компилироваться. И я думаю, что вы имеете в виду obj.properties вместо Object.properties.:) – Vlad from Moscow Sep 06 '15 at 17:21
-
Я не привязывался к конкретному языку, я привел простой пример, пользы от гетера – ActivX Sep 06 '15 at 17:27
-
-
-
Особенно такой момент важен когда с указателями работаешь в С++ это актуально! – ActivX Sep 06 '15 at 17:31
-
2На самом деле этот пример спорный, так как третье предложение, фактически, ничем не отличается от второго. Функция может возвращать, например, ссылку на указатель. – Vlad from Moscow Sep 06 '15 at 17:36
-
1Думаю, что для многих будет непонятен данный комментарий: // не откомпилится так как на выходе константа. Что он означает? – Vlad from Moscow Sep 06 '15 at 17:41
-
Помимо всего прочего, уже написанного выше, добавлю от себя, что в многопоточном приложении это не рекомендация/аксиома/хороший тон, а просто необходимость. Так же, это позволяет реализовать атрибуты, не свойственные обычным ivar. К примеру: copy, weak, strong, уже упомянутый выше readonly.
В остальных же случаях, надо отталкиваться от задачи. Например, в каких-то жручих движках, где каждый чих на счету, возможно, лишний вызов метода будет злом. Так же иногда странно выглядят методы доступа для внутренних ivar. Не стоит забывать, что паттерны существуют для решения определенного круга задач, а не просто для слепого им следования ради самих паттернов.
В теории, с точки зрения ООП напрямую обращаться к полям считается плохим тоном:
class MyClass {
public:
int field;
};
MyClass a;
a.field = 1; // Это как бы неправильно
Чтобы работать с field нужно написать методы (например, геттеры и сеттеры):
class MyClass {
private:
int field;
public:
int getField() { return field; }
void setField(int value) { field = value; }
};
MyClass a;
a.setField(1); // Это как бы правильно
- 2,042
-
7"Считается плохим тоном .. нужны геттеры и сеттеры .. это дает очевидные* преимущества"* Такой ответ на вопрос не содержит ответа. – Kromster Sep 07 '15 at 05:19
-
Почему не ответ, ещё какой ответ! Есть в математике такое понятие, как аксиома... Так вот в ООП не советуют напрямую обращаться к полям - это как аксиома, поэтому используют методы (например, геттеры и сеттеры). – sitev_ru Sep 07 '15 at 05:45
-
"Так вот в ООП не советуют напрямую обращаться к полям" - это всего лишь одна из причин наличия геттеров/сеттеров и требует обоснования (и оно дано выше в других ответах). – Kromster Sep 07 '15 at 05:54
-
Те кто придумал ООП, прописали, что этой парадигме не советует прямое обращение к функциям. Новичок, который начинает пользоваться ООП, задав вопрос, который он задал, в первую очередь должен был услышать, что так прописано в парадигме ООП. – sitev_ru Sep 07 '15 at 06:34
-
7Кто и кому не советует обращаться к полям? Кто считает это плохим тоном? Каковы преимущества (не всем очевидно)? Кто придумал ООП и где они прописали всё это? – Nick Volynkin Sep 07 '15 at 07:19
-
5Нужно хотя бы расписать, что за "очевидные" преимущества дает создание геттеров и сеттеров. Они очевидны тем, кто давно занимается разработкой в ООП, но не вчерашнему школьнику. – Vesper Sep 07 '15 at 07:20
-
"Нужно хотя бы расписать"... Зачем??? До этогож сколько было расписано )) Ответ на заданный здесь вопрос - это суммарный ответ всех, кто ответил... Зачем каждому расписывать? – sitev_ru Sep 07 '15 at 07:22
-
2@sitev_ru слово "очевидные" означает "несомненный, бесспорный, понятный с первого взгляда". ваш ответ, очевидно, эквивалентен "преимущества понятны с первого взгляда". хотя сам по себе факт наличия вопроса показывает, что это не так. он никак не суммирует и не дополняет остальные ответы, так что смысла в нем, очевидно, нет. – Sep 07 '15 at 07:36
-
1Стековерфлоу превращается в сайт поиска лингвистических ошибок))). Ну хорошо, удалил строчку со словом ОЧЕВИДНОЕ... Так правильно? )) – sitev_ru Sep 07 '15 at 09:59
-
1Поразительно, что 2 по сути одинаковых ответа (ООП -> инкапсуляция --> делаем из простого кода "код из много-много букв") так по разному оценены. – avp Sep 07 '15 at 10:59
-
1@avp суть разная. в одном ответе сказано, зачем инкапсуляция нужна, во втором - нет. – Sep 09 '15 at 10:26