Аксессоры против публичных членов

У меня есть класс с большим количеством встроенных членов типа с доступом для чтения/записи. Должен ли я сделать их публичными членами и предоставить методы get/set для каждого из них? Как насчет структур?


person jackhab    schedule 22.03.2009    source источник


Ответы (5)


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

person Nemanja Trifunovic    schedule 22.03.2009
comment
Противникам: я воспользовался советом самого Страуструпа: artima.com/intv/goldilocks3.html Бьерн Страуструп: Мое эмпирическое правило состоит в том, что у вас должен быть настоящий класс с интерфейсом и скрытым представлением тогда и только тогда, когда вы можете рассмотреть инвариант для класса. - person Nemanja Trifunovic; 22.03.2009
comment
Это определенно так. Далее в том же тексте: Да. Если все данные могут иметь любое значение, то класс не имеет особого смысла. Возьмите одну структуру данных, которая имеет имя и адрес. Любая строка — это хорошее имя, и любая строка — это хороший адрес. Если это так, то это структура. - person Nemanja Trifunovic; 22.03.2009
comment
Продолжение: Не имейте ничего личного. Не делайте ничего глупого, например, спрячьте поле имени и адреса с функциями get_name и set_address, а также get_name и set_name. Или, что еще хуже, создайте виртуальный базовый класс с виртуальными функциями get_name, set_name и так далее. - person Nemanja Trifunovic; 22.03.2009
comment
Я думаю, что противники (я не был одним из них) могут учитывать, что помимо неизменности есть и другие проблемы, такие как виртуальное поведение, удобство, самодокументирование и т. д. - person ; 22.03.2009
comment
Хотя я согласен, что было бы вежливо и полезно, если бы они объяснили свои отрицательные голоса. - person ; 22.03.2009
comment
Я также не из тех, кто проголосовал против, но мне бы хотелось увидеть обоснование вашего ответа, а не просто заявление. Это заслужило бы голосование. :) - person razlebe; 22.03.2009
comment
Полностью согласен с тем, что голосующие против должны дать хотя бы один комментарий для голосования против. - person anand; 22.03.2009

Вся причина иметь аксессоры (геттеры) и модификаторы (сеттеры) состоит в том, чтобы обеспечить себе дополнительный уровень косвенности.

Этот дополнительный уровень косвенности позволяет вам предоставить общедоступному интерфейсу представление вашей переменной только для чтения, не позволяя изменять член данных. Вы все еще можете использовать частный или защищенный сеттер.

Сеттеры позволяют выполнять специальную проверку ошибок, проверку и исправление при установке значения. Например, setDirectory(const std::string &strPath), вы можете убедиться, что есть завершающая косая черта, если пользователь ее не указал. Это гарантирует, что ваше состояние класса всегда будет действительным.

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

Дополнительный уровень косвенности для геттеров/сеттеров также позволяет вам изменять элемент данных, который они инкапсулируют.

С помощью геттера вы также можете получить различные представления ваших данных, например: getMinutes, когда ваш элемент данных фактически хранится в секундах.

Это не причина их использования, но приятный побочный эффект использования геттеров и сеттеров заключается в том, что вы можете установить точку останова внутри своего модификатора, например, чтобы точно видеть, когда он изменяется.

Следует ли вам их использовать или нет, зависит от ваших потребностей. Если у вас так много членов, что предоставить геттеры и настройки очень сложно, вы можете рассмотреть возможность хранения членов данных в структуре и использования этой структуры внутри вашего класса. Вы даже можете предоставить геттеры/сеттеры для объекта сразу для всей структуры.

person Brian R. Bondy    schedule 22.03.2009

Во-первых, если в вашем классе много элементов данных, возможно, он плохо спроектирован. Возможно, вам придется подумать о разделении его на несколько классов или сохранении данных в таких структурах, как карты.

Что касается предоставления доступа, вопрос заключается в том, захотите ли вы когда-нибудь изменить доступ, возможно, предотвратив его. Если ответ да, то вам нужны функции доступа. С другой стороны, если ваш класс на самом деле просто набор битов без какого-либо поведения, сделайте его структурой.

person Community    schedule 22.03.2009

Вы должны использовать только общедоступные данные

  • в структурах, которые вы не подвергаете клиентскому коду (например, функторы в стиле связывания) - бесполезно защищать структуры, которые никто извне никогда не получит
  • если их типы инкапсулируют логику их установки/получения (например, если вы создаете класс ObservableAttribute)
  • если они являются константными членами в неизменной структуре (вы ничего не можете сделать, кроме как прочитать их, если они неизменяемы)

Если вы создаете общедоступный элемент данных, вы должны быть уверены, что его значение полностью ортогонально другим членам класса. Например, вы отключаете будущие возможности

  • наблюдение за изменениями члена
  • заставить член играть любую роль в инварианте класса
  • отключение доступа к участнику
  • изменение реализации члена (например, вычисляемый, кэшированный или хранимый), если это необходимо для производительности.
person jpalecek    schedule 22.03.2009

Использование методов get/set для закрытых/защищенных элементов данных — плохой дизайн.

Это заставляет клиентский код зависеть от деталей реализации вашего класса.

Изменения в вашем классе вызывают изменения в клиентском коде.

Однако можно использовать методы get/set для открытых членов. Но всегда лучше их избегать.

person anand    schedule 22.03.2009
comment
Я проголосовал за это, так что это было как минимум 4 отрицательных голоса :) Серьезно, я думал, что общеизвестно, что геттеры/сеттеры - плохой дизайн. Страшный. - person Nemanja Trifunovic; 23.03.2009
comment
Хорошо, вопрос был в том, можно ли использовать геттеры/сеттеры? В большинстве случаев это плохой дизайн, и это то, что я ответил. Из большинства ответов выше тот же вывод. Я не уверен, что это общеизвестно для всех. - person anand; 23.03.2009