Подтвердить что ты не робот

Какая польза для публичных переменных?

Я полный новичок с тоннами? в моем уме и многого, чтобы испытать с С++ еще! Было что-то, что я нахожу действительно запутанным, и это использование публичных переменных, я видел тонны кода следующим образом:

class Foo {

private:
    int m_somePrivateVar;

public:
    void setThatPrivateVar (int const & new_val) {
        m_somePrivateVar = new_val;
    }

    int getThatPrivateVar (void) const {
        return m_somePrivateVar;
    }

};

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

Спасибо заранее.

4b9b3361

Ответ 1

Скрывая теперь переменную и добавляя методы, конструктор классов позволяет вставлять произвольный код в эти методы в будущем, не разбивая тонны кода, который использует атрибуты напрямую.

Также обратите внимание, что предоставление большого количества методов accessor/mutator обычно является признаком того, что вашему дизайну класса нужен другой взгляд на возможное улучшение. Методы класса должны реализовывать фактическую логику, а не только предоставлять доступ каждому члену.

Я использую общедоступные переменные только в форме struct. Например, у меня может быть таблица базы данных, которая представляет сопоставление строк и значений, где значение представляет собой составную структуру данных. Я бы просто написал структуру и использовал, например, std::map<std::string, MyStruct> для представления таблицы базы данных. Мне не нужно на самом деле работать над данными, просто иметь возможность искать их и использовать, когда это требуется.

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

Ответ 2

ИМО - самая убедительная причина для сеттеров/геттеров изолировать изменение. Если вам нужно добавить проверку диапазона, например, если у вас уже есть сеттер, вы можете легко сделать это в своем сеттере, не влияя на код клиента. Если у вас еще нет сеттера, тогда весь клиентский код необходимо обновить, чтобы использовать геттеры/сеттеры, которые могут быть кошмаром.

Ответ 3

Я согласен, в частности, с другими ответами, касающимися использования методов getter и setter, чтобы допускать будущие изменения, но по-прежнему существует фундаментальная проблема, вы подвергаете внутренние данные вашего объекта другим изменяемым объектам.

Лучше попросить объект выполнить какое-то действие над данными, которые он хранит, посредством метода, а не рассматривать объект как совокупность значений.

Вот интересная статья о Почему методы Getter и Setter Evil, они написаны с учетом Java, но то же самое относится к С++.

Ответ 4

Один аргумент работает примерно так:

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

Использование "getters" и "seters" дает вам некоторую гибкость, встроенную в соединение ваших объектов.

Ответ 5

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

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

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

Ответ 6

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

Ответ 7

ОК. Насколько я понимаю, ваш вопрос таков: зачем делать переменную private, а затем создавать две функции, которые просто извлекают значение и устанавливают значение без каких-либо проверок? Если бы были проверки, вы бы поняли, не так ли? Например, если вы установите поле час класса Время, убедитесь, что hour <= 24 - хорошая идея.

Но когда никаких проверок не применяется, идея такова: если в какой-то момент вы решите изменить настройки и получить функции, например, выполнить некоторые проверки в них, весь код, который использовал ваш класс не перекомпилировать

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

Когда вы используете общедоступные переменные? Когда вы делаете объекты, которые не имеют поведения. Это всего лишь конгломерат данных. Например, см. std::pair. Пара - это просто структура с общедоступными first и second.

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

HTH

Ответ 8

Как говорит Скотт Мейерс в книге Effective С++: избегайте использования данных в публичном интерфейсе. Зачем? потому что его легче кодировать (все это функция-член), также у вас больше контроля над доступом к этой переменной, а также о том, что Дуг Т. и другие говорили об функциональной абстракции.

Если вам не нужен класс (например, в вашем примере), у вас есть выбор использования структуры...

Посмотрите этот пост, написанный Скоттом, если у вас нет книги:)

Ответ 9

Я не могу согласиться с этим мнением, что общественные члены являются злыми. С++ не является С#. Я всегда избегал вещей, которые мне действительно не нужны при кодировании на С++. Использование публичных пользователей совершенно нормально, если

  • ваши общедоступные переменные не могут быть установлены на undefined, вне границ или как-то испорченные значения
  • вы знаете, что никто не попытается испортить ваш объект (это означает, что модули, использующие его, знают точно, что с ним делать)
  • вам не нужны никакие другие дополнительные проверки или модификации объекта, вызванные действием get/set
  • вы на 100% уверены, что в будущем вам не понадобятся какие-либо из перечисленных вещей.

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

В качестве ссылки прочитайте рекомендации С++ (C.131)

Ответ 10

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

Некоторые языки программирования (модели ООП) используют свойства для той же идеи. Если ваш открытый интерфейс состоит только из кода, вы можете в любой момент изменить внутреннюю работу, оставив интерфейс (и другой код, который его использует) неповрежденным. Если ваш публичный интерфейс содержит данные, вы ограничиваете возможности своего будущего развития.

Ответ 11

Я знаю, что в Java мы используем общедоступные переменные, по сути,

публичный статический окончательный

как средство указания констант перед перечислением.

Например,

class Direction
{

public static final String NORTH = "north";
...
}

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

Ответ 12

В большинстве случаев приемники и сеттеры действительно являются хорошей практикой. Но факт в том, что ваш текущий пример слишком прост и поэтому не является хорошим кандидатом для защиты доступа частных членов через get/set().

Ответ 13

Одна из наиболее интересных тенденций - автоматические свойства. Поэтому вместо того, чтобы писать геттеры и сеттеры, вам просто нужно написать свойство, а компилятор сделает все остальное. У вас все еще есть возможность писать геттеры и сеттеры, но вам не нужно писать весь код плиты котла для того, что должно быть только 1 строкой. Если вам нужно добавить проверку диапазона и т.д. Позже, вы можете просто создать свойство старомодным способом и сохранить интерфейс в своем классе тем же.

Я видел это в последних версиях С#, Objective-C и VB, и это может быть весьма полезно. Реализация VB не обеспечивает такой гибкости, как С#, но я уверен, что она будет быстро догонять.

Ответ 14

Мне не очень нравится писать аксессоры, которые ничего не делают. У меня есть две причины для этого отношения.

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

  • Теперь вы делаете дополнительную работу для чего-то, что может или не может произойти в будущем. Это вариация " преждевременная оптимизация".

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