У меня есть класс с переменной, которая является частной, и у класса есть получатель и установщик для этой переменной. Почему бы не сделать эту переменную общедоступной?
Я думаю, что вам нужно использовать только геттеры и сеттеры, если вам нужно выполнить какую-либо операцию, кроме set или get. Пример:
void my_class::set_variable(int x){
/* Some operation like updating a log */
this->variable = x;
}
this->variable = x + 5
или вызватьUpdateStatistics
функцию в установщике, и в этих случаяхclassinstancea->variable = 5
возникнут проблемы.set_inch
,set_centimeter
,get_inch
,get_centimeter
, с некоторыми пугающими действиями.Ответы:
Вы когда-нибудь слышали о недвижимости?
Свойство - это поле, которое имеет «встроенные» методы доступа (методы получения и установки). Java, например, не имеет свойств, но рекомендуется записывать методы получения и установки в закрытое поле. C # имеет свойства.
Итак, зачем нам геттеры и сеттеры? В основном это нужно для защиты / защиты поля. Например, вы не обращаетесь к полю в ссылке на память, вы обращаетесь к методу, который затем изменит поле (ссылку). Этот метод может выполнять некоторые операции, которые пользователь не хочет знать ( инкапсулируя поведение ), как в вашем примере. Представьте, например, что дюжина классов использует ваше открытое поле, и вам нужно изменить способ его использования ... Вам нужно будет посмотреть на каждый из этих классов, чтобы изменить способ использования поля ... Не так что "ООлыш".
Но, например, если у вас есть логическое поле с именем dead. Вы должны дважды подумать, прежде чем объявлять setDead и isDead. Вы должны написать средства доступа, которые будут удобочитаемыми для человека , например, kill () вместо setDead.
Тем не менее, существует множество платформ, которые предполагают, что вы следуете соглашению об именах JavaBean (здесь речь идет о Java), поэтому в этих случаях вы должны объявлять все методы получения и установки после соглашения об именовании.
источник
foo.bar = biz.baz+5
вызвать функциюbiz
для оценкиbaz
, затем добавить к ней пять и вызвать функцию,foo
чтобы установитьbar
полученное значение. Такие перегрузки не называются «свойствами», но они могут служить той же цели.Это не самое популярное мнение, но я не вижу большой разницы.
Сеттеры и геттеры - довольно плохая идея. Я думал об этом и, честно говоря, я не могу придумать разницу между установщиком / получателем свойства и публичной переменной на практике.
В THEORY установщик и получатель или свойство добавляют место для выполнения некоторых дополнительных действий, когда переменная установлена / получена, и теоретически они изолируют ваш код от изменений.
В действительности я редко вижу сеттеры и геттеры, используемые для добавления действия, и когда вы действительно хотите добавить действие, вы хотите добавить его ко ВСЕМ установщикам или получателям класса (например, протоколирование), что должно заставить вас думать, что быть лучшим решением.
Что касается изоляции проектных решений, если вы измените int на long, вам все равно придется изменить сеттеры и, по крайней мере, проверить каждую строку, которая обращается к ним вручную, - не так много изоляции.
В любом случае по умолчанию следует избегать изменчивых классов, поэтому добавление сеттера должно быть последним средством. Это смягчается с помощью шаблона построителя, где значение может быть установлено до тех пор, пока объект не будет в желаемом состоянии, тогда класс может стать неизменным, и ваши установщики будут выдавать исключения.
Что касается геттеров - я до сих пор не могу придумать большую разницу между геттером и публичной конечной переменной. Проблема здесь в том, что это плохой ОО в любом случае. Вы не должны запрашивать значение у объекта и оперировать им - вы должны просить объект выполнить операцию за вас.
Кстати, я никоим образом не защищаю публичные переменные - я говорю, что сеттеры и геттеры (и даже свойства) слишком близки к тому, чтобы уже быть публичными переменными.
Большая проблема заключается в том, что люди, которые не являются программистами OO, слишком искушены использовать сеттеры и геттеры для превращения объектов в шары свойств (структуры), которые передаются и обрабатываются, в значительной степени противоположно тому, как работает объектно-ориентированный код.
источник
Пользователь геттеров и сеттеров переходит на принцип инкапсуляции . Это позволит вам изменить то, как все работает внутри класса, и поддерживать все в рабочем состоянии.
Например, если 3 других объекта звонят,
foo.bar
чтобы получить значение bar, и вы решаете изменить имя bar, то у вас возникла проблема. Если вызванные объектыfoo.bar
вам придется изменить все классы, которые имеют это. Если используется сеттер / геттер, то вам нечего менять. Другой возможностью является изменение типа переменной, в этом случае просто добавьте код преобразования в метод получения / установки, и все в порядке.источник
Использование методов получения и установки также позволяет вам контролировать, какой контент хранится в определенной переменной. Если контент должен иметь определенный тип или значение, часть кода установщика может быть направлена на то, чтобы новое значение соответствовало этим требованиям. Если переменная общедоступна, вы не можете обеспечить выполнение этих требований.
Этот подход также делает ваш код более адаптируемым и управляемым. Гораздо проще вносить изменения в архитектуру класса, если у вас есть функции, которые скрывают эту архитектуру от всех других классов или функций, использующих этот класс. Уже упомянутое изменение имени переменной - это только одно из многих изменений, которые намного легче сделать, если у вас есть такие функции, как геттеры и сеттеры. Общая идея состоит в том, чтобы сохранить как можно больше приватности, особенно переменных вашего класса.
источник
Вы говорите: «Единственный случай, я думаю, что вы должны использовать геттеры и сеттеры, это если вам нужно выполнить какую-то операцию помимо set или get».
Вы должны использовать геттеры и сеттеры, если в какой-то момент в будущем вам может понадобиться выполнить какую-либо операцию помимо set и get, и вы не захотите менять тысячи строк исходного кода, когда это произойдет.
Вы должны использовать геттеры и сеттеры, если вы не хотите, чтобы кто-то брал адрес переменной и передавал ее, что приводило к катастрофическим последствиям, если бы эту переменную можно было изменить без упоминания в ней исходного кода или даже после того, как объект перестал существовать. ,
источник
Прежде всего, давайте проясним парадигму.
Где полезен геттер / сеттер?
Полезны ли геттеры / сеттеры в структурах данных? Нет .
Структура данных - это спецификация макета памяти, которая является общей для семейства функций и управляется ими.
Как правило, любая старая новая функция может прийти и манипулировать структурой данных, если она делает это так, чтобы другие функции все еще могли ее понять, то функция присоединяется к семейству. В противном случае это мошенническая функция и источник ошибок.
Не поймите меня неправильно, может быть несколько семейств функций, борющихся за эту структуру данных с повсеместными доработками, поворотами и двойными агентами. Хорошо, когда у каждого из них есть своя собственная структура данных, с которой можно поиграть, но когда они делятся ею ... просто представьте, что несколько криминальных семей не согласны с политикой, это может быстро превратиться в беспорядок.
Учитывая, что может достичь беспорядок семейства расширенных функций, есть ли способ кодировать структуру данных, чтобы мошеннические функции не все испортили? Да, они называются объектами.
Полезны ли методы получения / установки в объектах? Нет .
Весь смысл обертывания структуры данных в объекте состоял в том, чтобы гарантировать, что никакие мошеннические функции не могут существовать. Если функция хотела присоединиться к семье, ее сначала нужно было тщательно проверить, а затем стать частью объекта.
Цель / цель метода получения и установки состоит в том, чтобы позволить функциям вне объекта напрямую изменять структуру памяти объекта. Это звучит как открытая дверь, чтобы позволить жуликам ...
The Edge Case
Существуют две ситуации, в которых публичный метод получения / установки имеет смысл.
Контейнеры и контейнерные интерфейсы являются прекрасными примерами обеих этих двух ситуаций. Контейнер управляет структурами данных (связанный список, карта, дерево) изнутри, но контролирует определенный элемент всем и каждому. Интерфейс абстрагирует это и полностью игнорирует реализацию и описывает только ожидания.
К сожалению, многие реализации делают это неправильно и определяют интерфейс объектов такого типа, чтобы предоставить прямой доступ к реальному объекту. Что-то типа:
Сломано. Реализации Контейнера должны явно передать управление своими внутренними компонентами тому, кто их использует. Я еще не видел язык изменяемых значений, где это нормально (языки с семантикой неизменяемых значений по определению хороши с точки зрения повреждения данных, но не обязательно с точки зрения шпионажа данных).
Вы можете улучшить / исправить геттеры / сеттеры, используя только семантику копирования или прокси:
Возможно, мошенническая функция все еще может играть хаос (при достаточных усилиях большинство вещей возможно), но семантика копирования и / или прокси уменьшает вероятность появления ряда ошибок.
Частные добытчики / сеттеры
Это последний оплот геттеров и сеттеров, работающих над типом напрямую. На самом деле я бы даже не назвал эти геттеры и сеттеры, а аксессорами и манипуляторами.
В этом контексте иногда манипулирование определенной частью структуры данных всегда / почти всегда / обычно требует ведения специального бухгалтерского учета. Скажем, когда вы обновляете корень дерева, кэш внешнего вида должен быть очищен, или когда вы обращаетесь к внешнему элементу данных, необходимо получить / снять блокировку. В этих случаях имеет смысл применить принцип DRY и объединить эти действия вместе.
В частном контексте другие функции в семье все еще могут обходить эти «методы получения и установки» и манипулировать структурой данных. Следовательно, почему я думаю о них больше как о принадлежностях и манипуляторах. Вы можете получить доступ к данным напрямую или положиться на другого члена семьи, чтобы получить эту часть права.
Защищенные добытчики / сеттеры
В защищенном контексте это не сильно отличается от публичного контекста. Зарубежные, возможно, мошеннические функции хотят получить доступ к структуре данных. Так что нет, если они существуют, они действуют как публичные добытчики / установщики.
источник
Из опыта C ++, метод установки / получения полезен для 2 сценариев:
Помимо этого, безопасность является действительной точкой, но ее важность ограничена очень немногими приложениями для разработки, такими как модули входа или доступа к базе данных. Зачем беспокоиться о дополнительном кодировании, когда только несколько человек используют ваш модуль?
источник