Общедоступные Элементы данных по сравнению с Методами считывания, Методами set

Я в настоящее время работаю в QT и так C++. У меня есть классы, который имеет частные элементы данных и общедоступные функции членства. У меня есть общедоступные методы считывания и методы set для элементов данных, доступных в классе.

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

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

70
задан liaK 4 June 2010 в 19:08
поделиться

12 ответов

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

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

РЕДАКТИРОВАТЬ: После комментария, который я сделал к другому ответу.

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

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

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

72
ответ дан 24 November 2019 в 13:19
поделиться

Использование геттеров и сеттеров позволит вам изменить способ передачи значений пользователю.

Рассмотрим следующее:

double premium;
double tax;

Затем вы пишете код повсюду, используя это значение premium для получения премии:

double myPremium = class.premium;

Ваши спецификации только что изменились, и премия с точки зрения пользователя должна быть premium + tax

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

Если бы вы реализовали это так:

double premium;
double tax;

double GetPremium(){return premium;};

Весь ваш код использовал бы GetPremium(), а изменение tax было бы в одну строчку:

double premium;
double tax;

double GetPremium(){return premium + tax;};
1
ответ дан 24 November 2019 в 13:19
поделиться

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

2
ответ дан 24 November 2019 в 13:19
поделиться

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

5
ответ дан 24 November 2019 в 13:19
поделиться

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

Изменить: идея о том, что контроль доступа к данным представляет собой инкапсуляцию, в основном неверна. Инкапсуляция заключается в сокрытии деталей реализации (в общем!) , а не контроля доступа к данным.

Инкапсуляция дополняет абстракцию: абстракция имеет дело с внешне видимым поведением объекта, а инкапсуляция занимается сокрытием деталей того, как это поведение реализуется.

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

Конечно, это нужно учитывать в контексте: для некоторых классов «данные» вообще не являются хорошей абстракцией. Вообще говоря, если вы можете предоставить более высокоуровневые операции вместо данных, это предпочтительнее.Тем не менее, существуют классы, для которых наиболее удобной абстракцией является чтение и запись данных - и в этом случае (абстрактные) данные должны быть сделаны видимыми, как и любые другие данные. Тот факт, что получение или установка значения может включать в себя нечто большее, чем простое копирование битов, является деталью реализации, которая должна быть скрыта от пользователя.

10
ответ дан 24 November 2019 в 13:19
поделиться

Я предлагаю не иметь открытых членов данных (кроме структур POD). Я также не рекомендую иметь геттеры и сеттеры для всех ваших членов данных. Лучше определите чистый открытый интерфейс для вашего класса. Это может включать методы, которые получают и / или устанавливают значения свойств, и эти свойства могут быть реализованы как переменные-члены. Но не создавайте геттеры и сеттеры для всех ваших участников.

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

1
ответ дан 24 November 2019 в 13:19
поделиться

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

0
ответ дан 24 November 2019 в 13:19
поделиться

Исходя из строго практических соображений, я бы посоветовал вам начать с того, чтобы сделать все ваши элементы данных закрытыми, И сделать закрытыми их геттеры и сеттеры. Когда вы узнаете, что на самом деле нужно остальному миру (то есть вашему «(1) сообществу пользователей»), вы можете раскрыть соответствующие геттеры и / или сеттеры или написать публичные методы доступа с надлежащим контролем.

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

3
ответ дан 24 November 2019 в 13:19
поделиться

Если у вас есть геттеры и сеттеры для каждого из ваших элементов данных, нет смысла делать данные приватными. Вот почему использование геттеров и сеттеров для каждого из ваших элементов данных - плохая идея. Рассмотрим класс std :: string - у него (вероятно) есть ОДИН получатель, функция size () и вообще нет сеттеров.

Или рассмотрим объект BankAccount - нужно ли иметь сеттер SetBalance () для изменения текущего баланса? Нет, большинство банков не будут благодарить вас за такое внедрение. Вместо этого нам нужно что-то вроде ApplyTransaction (Transaction & tx) .

23
ответ дан 24 November 2019 в 13:19
поделиться

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

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

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

5
ответ дан 24 November 2019 в 13:19
поделиться

Геттеры и сеттеры позволяют вам применять логику к вводу/выводу из закрытых членов, контролируя доступ к данным (инкапсуляция для тех, кто знает термины ОО).

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

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

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

10
ответ дан 24 November 2019 в 13:19
поделиться

Нет, это даже удаленно не одно и то же.

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


1. Открытый член данных:

  • обеспечивает доступ как для чтения, так и для записи (если не константный) для элемента данных
  • демонстрирует тот факт, что объект данных физически существует и физически является членом этого класса (позволяет создавать указатели указателя- to-member type для этого члена данных)
  • предоставляет доступ lvalue к члену данных (позволяет создавать обычные указатели на член)


2. Метод, который возвращает ссылку на часть данных (возможно, на частный член данных):

  • обеспечивает доступ как для чтения, так и для записи (если не константный) к данным
  • раскрывает тот факт, что объект данных физически существует, но не раскрывает , что он физически является членом этого класса (не позволяет создавать указатели типа указатель на член на данные)
  • предоставляет доступ к данным по lvalue (позволяет создавать обычные указатели на него)


3.Методы получения и / или установки (возможно, доступ к частному элементу данных):

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

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

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

Конечно, есть вариации каждого подхода. Например, метод получения может возвращать константную ссылку на данные, которая помещает ее где-то между (2) и (3).

34
ответ дан 24 November 2019 в 13:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: