Прежде всего, давайте проясним парадигму.
- Структуры данных -> схема памяти, которую можно перемещать и манипулировать с помощью хорошо осведомленных функций.
- Объекты -> автономный модуль, который скрывает свою реализацию и предоставляет интерфейс, через который можно обмениваться данными.
Где полезен геттер / сеттер?
Полезны ли геттеры / сеттеры в структурах данных? Нет .
Структура данных - это спецификация макета памяти, которая является общей для семейства функций и управляется ими.
Как правило, любая старая новая функция может прийти и манипулировать структурой данных, если она делает это так, чтобы другие функции все еще могли ее понять, то функция присоединяется к семейству. В противном случае это мошенническая функция и источник ошибок.
Не поймите меня неправильно, может быть несколько семейств функций, борющихся за эту структуру данных с повсеместными доработками, поворотами и двойными агентами. Хорошо, когда у каждого из них есть своя собственная структура данных, с которой можно поиграть, но когда они делятся ею ... просто представьте, что несколько криминальных семей не согласны с политикой, это может быстро превратиться в беспорядок.
Учитывая, что может достичь беспорядок семейства расширенных функций, есть ли способ кодировать структуру данных, чтобы мошеннические функции не все испортили? Да, они называются объектами.
Полезны ли методы получения / установки в объектах? Нет .
Весь смысл обертывания структуры данных в объекте состоял в том, чтобы гарантировать, что никакие мошеннические функции не могут существовать. Если функция хотела присоединиться к семье, ее сначала нужно было тщательно проверить, а затем стать частью объекта.
Цель / цель метода получения и установки состоит в том, чтобы позволить функциям вне объекта напрямую изменять структуру памяти объекта. Это звучит как открытая дверь, чтобы позволить жуликам ...
The Edge Case
Существуют две ситуации, в которых публичный метод получения / установки имеет смысл.
- Часть структуры данных в объекте управляется объектом, но не контролируется объектом.
- Интерфейс, описывающий высокоуровневую абстракцию структуры данных, где ожидается, что некоторые элементы не будут контролировать объект реализации.
Контейнеры и контейнерные интерфейсы являются прекрасными примерами обеих этих двух ситуаций. Контейнер управляет структурами данных (связанный список, карта, дерево) изнутри, но контролирует определенный элемент всем и каждому. Интерфейс абстрагирует это и полностью игнорирует реализацию и описывает только ожидания.
К сожалению, многие реализации делают это неправильно и определяют интерфейс объектов такого типа, чтобы предоставить прямой доступ к реальному объекту. Что-то типа:
interface Container<T>
{
typedef ...T... TRef; //<somehow make TRef to be a reference or pointer to the memory location of T
TRef item(int index);
}
Сломано. Реализации Контейнера должны явно передать управление своими внутренними компонентами тому, кто их использует. Я еще не видел язык изменяемых значений, где это нормально (языки с семантикой неизменяемых значений по определению хороши с точки зрения повреждения данных, но не обязательно с точки зрения шпионажа данных).
Вы можете улучшить / исправить геттеры / сеттеры, используя только семантику копирования или прокси:
interface Proxy<T>
{
operator T(); //<returns a copy
... operator ->(); //<permits a function call to be forwarded to an element
Proxy<T> operator=(T); //< permits the specific element to be replaced/assigned by another T.
}
interface Container<T>
{
Proxy<T> item(int index);
T item(int index); //<When T is a copy of the original value.
void item(int index, T new_value); //<where new_value is used to replace the old value
}
Возможно, мошенническая функция все еще может играть хаос (при достаточных усилиях большинство вещей возможно), но семантика копирования и / или прокси уменьшает вероятность появления ряда ошибок.
- переполнение
- опустошения
- взаимодействия с подэлементом проверяются на тип / проверяются на тип (в типах с потерей языков это благо)
- Фактический элемент может быть или не быть резидентом памяти.
Частные добытчики / сеттеры
Это последний оплот геттеров и сеттеров, работающих над типом напрямую. На самом деле я бы даже не назвал эти геттеры и сеттеры, а аксессорами и манипуляторами.
В этом контексте иногда манипулирование определенной частью структуры данных всегда / почти всегда / обычно требует ведения специального бухгалтерского учета. Скажем, когда вы обновляете корень дерева, кэш внешнего вида должен быть очищен, или когда вы обращаетесь к внешнему элементу данных, необходимо получить / снять блокировку. В этих случаях имеет смысл применить принцип DRY и объединить эти действия вместе.
В частном контексте другие функции в семье все еще могут обходить эти «методы получения и установки» и манипулировать структурой данных. Следовательно, почему я думаю о них больше как о принадлежностях и манипуляторах. Вы можете получить доступ к данным напрямую или положиться на другого члена семьи, чтобы получить эту часть права.
Защищенные добытчики / сеттеры
В защищенном контексте это не сильно отличается от публичного контекста. Зарубежные, возможно, мошеннические функции хотят получить доступ к структуре данных. Так что нет, если они существуют, они действуют как публичные добытчики / установщики.
this->variable = x + 5
или вызватьUpdateStatistics
функцию в установщике, и в этих случаяхclassinstancea->variable = 5
возникнут проблемы.