Страницы

Поиск по вопросам

понедельник, 25 ноября 2019 г.

В чем смысл геттеров и сеттеров в C++ (и не только)?


В c++ я новичок и не могу понять, для чего, собственно, нужны геттеры и сеттеры?
Почему нельзя просто сделать переменные внутри класса глобальными и изменять непосредственн
их? В чем необходимость делать переменную приватной и создавать функции для ее модификации или получения ее значения?
    


Ответы

Ответ 1



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

Ответ 2



Главный смысл заключается в том, чтобы отделить реализацию от интерфейса. Таким образом, с одной стороны, изменения в реализации не влияют на пользовательски интерфейс класса, а, с другой стороны, пользователь класса, имеющий к нему доступ через открытый интерфейс, не сможет нарушить объявленное корректное поведение класса. В классе могут существовать зависимости между его членами. Поэтому объект класс должен быть осведомлен, когда какой-то член класса подвергся изменению со стороны пользователя, чтобы в соответствии с этим изменением привести в соответствие состояния других членов класса. Например, если ваш класс температуры содержит два члена данных, температуру по Цельси и температуру по Фаренгейту, то если пользователь изменил одну из температур, то объект класса должен пересчитать другую температуру, чтобы их значения были согласованы между собой. Обобщенно это называется одним словом инкапсуляция. Желая правильно написать это слово - инкапсуляция, - я посмотрел, как оно пишется в словаре, и словарь помимо всего прочего выдал такое пояснение к слову: Инкапсуляция - иммунная реакция у насекомых в ответ на паразитарную инвазию. Перефразируя это определение по отношению к классам, можно сказать, что инкапсуляци в ООП - это иммунная реакция класса в ответ на неправильные действия пользователей в отношении его объектов. :)

Ответ 3



Пример типичной ошибки Object obj = new Object(); if(obj.properties = null) return false; // Опечатка, которую трудно отловить if(obj.getProperties() = null) return false; // не скомпилируется, так как результату функции нельзя присвоить значение if(obj.getProperties() == null) return false; // Правильный вариант getProperties() возвращает значение, а в операции присваивания в левой части может участвовать только переменная!

Ответ 4



Помимо всего прочего, уже написанного выше, добавлю от себя, что в многопоточно приложении это не рекомендация/аксиома/хороший тон, а просто необходимость. Так же, это позволяет реализовать атрибуты, не свойственные обычным ivar. К примеру: copy, weak, strong, уже упомянутый выше readonly. В остальных же случаях, надо отталкиваться от задачи. Например, в каких-то жручих движках, где каждый чих на счету, возможно, лишний вызов метода будет злом. Так же иногда странно выглядят методы доступа для внутренних ivar. Не стоит забывать что паттерны существуют для решения определенного круга задач, а не просто для слепого им следования ради самих паттернов.

Ответ 5



В теории, с точки зрения ООП напрямую обращаться к полям считается плохим тоном: 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); // Это как бы правильно

Комментариев нет:

Отправить комментарий