Правильное использование - методы доступа/геттеры против обычных методов

У меня возникают проблемы с разграничением между аксессорами/геттерами, которые представляют свойства объекта и обычные методы. В C++ соглашения об именах для методов доступа и обычных методов различаются (например, руководство по стилю Google предлагает строчные буквы для методов доступа и PascalCase для обычных методов). Более того, порядок обычных методов и методов доступа/геттеров (до или после) также подлежит соглашениям. В Java может возникнуть дилемма, должен ли метод начинаться с «получить» или «вычислить»/«найти», чтобы указать геттер и обычный метод соответственно. В C# существует дилемма, что должно быть свойством, а что методом. Всякий раз, когда я создаю новый класс, я не знаю, как классифицировать методы на обычные методы и геттеры.

Есть ли простой способ определить, что является свойством объекта/аксессора/геттера и что должно быть обычным методом?

И имеет ли что-либо из следующего какое-то отношение к различию между аксессором/геттером и обычным методом:

  1. Вычисление дешево
  2. Возвращается новый объект (или его копия) вместо (константной) ссылки
  3. нет сеттера
  4. Есть способ повлиять на это «свойство», но косвенно.

Чтобы проиллюстрировать это, вот пример (на C++): Предположим, я хочу создать структуру данных, которая может содержать фиксированное количество элементов, и помимо операций вставки/удаления она предлагает ряд методов, которые работают с содержащимися элементами ( т.е. среднее, медиана, минимум, максимум и т.д.). Теперь возьмем, например, функцию, которая вычисляет среднее значение; можно сказать, что это свойство объекта, и пересчитывать его всякий раз, когда элемент вставляется/удаляется, и, таким образом, рассматривать его как геттер, такой как const double& average(). Другой способ — вычислить его по запросу и рассматривать как обычный метод, т. е. double ComputeAverage(). Кроме того, предположим, что есть метод, который возвращает набор содержащихся элементов; его можно рассматривать как геттер const set<int>& unique_elements(), если нет необходимости вычислять его каждый раз, но если класс вычисляет его каждый раз, то set<int> ComputeUniqueElements() будет более подходящим.


person eold    schedule 28.05.2011    source источник
comment
Поскольку в С++ нет формального понятия свойств (это всего лишь методы, если говорить о языке), не является ли это просто вопросом стиля/предпочтения программирования? Вы можете назвать свои методы, как вам нравится, и заставить их вести себя так, как вам больше всего подходит...   -  person Jeremy Friesner    schedule 29.05.2011
comment
@Jeremy: Что касается языка, то методов не существует. Вы имели в виду функцию, которая является членом? Или тот, который не является статическим? Или тот, который виртуальный? Или тот, который чистый? Во избежание недоразумений предпочитайте стандартизированную терминологию: вместо метода говорите функцию с префиксом тех спецификаторов, которые уместны.   -  person Lightness Races in Orbit    schedule 29.05.2011
comment
Да, нестатические функции-члены.   -  person eold    schedule 29.05.2011
comment
@Tomalak Я хотел использовать ту же терминологию, что и на оригинальном плакате, чтобы не превращать дискуссию в непродуктивную языковую юриспруденцию.   -  person Jeremy Friesner    schedule 29.05.2011
comment
@Jeremy: В своем предыдущем комментарии вы говорили о формальностях, а что касается языка, то оспаривайте, когда я использую тот же подход.   -  person Lightness Races in Orbit    schedule 29.05.2011
comment
У меня возникают проблемы с разграничением между аксессорами/геттерами, которые представляют свойства объекта и обычные методы. Хорошо. Чем раньше вы поймете, что нет разницы, тем лучше. Аксессор - это обычный метод, который просто получает/устанавливает определенное значение члена. Если вы измените реализацию класса так, чтобы он задавал несколько членов, или иным образом измените хранилище, интерфейс не должен измениться. Документы по стилю Google — это не Бог, и с ними не следует обращаться как с таковыми.   -  person Nicol Bolas    schedule 19.07.2012


Ответы (1)


Создание разделения между средствами доступа и "обычными методами" - плохая идея. Метод есть метод; это функция-член, которая имеет определенный эффект. Тот факт, что функция-член просто устанавливает значение переменной-члена или возвращает значение переменной-члена, представляет собой деталь реализации.

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

Допустим, у вас есть name "свойство" в вашем классе. Первоначально вы сохраняете его как std::string. Вы предоставляете функции для получения и изменения имени. Все хорошо и хорошо.

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

В C++ соглашения об именах для методов доступа и обычных методов различаются (например, руководство по стилю Google предлагает строчные буквы для методов доступа и PascalCase для обычных методов).

Руководство по стилю Google не представляет C++ или его программистов; он представляет только то, что делает Google.

person Nicol Bolas    schedule 18.07.2012