По-перше, давайте зрозуміти парадигму.
- Структури даних -> макет пам'яті, яким можна пройти та керувати відповідними знаннями функціями.
- Об'єкти -> автономний модуль, який приховує його реалізацію та забезпечує інтерфейс, через який можна передавати інформацію.
Де корисний геттер / сетер?
Чи корисні геттери / сетери в структурах даних? Ні.
Структура даних - специфікація макета пам’яті, яка є загальною для сімейства функцій та якою керує.
Як правило, будь-яка стара функція може поєднуватися і маніпулювати структурою даних, якщо вона робить це таким чином, щоб інші функції все-таки могли її зрозуміти, тоді ця функція приєднується до родини. Інакше це шахрайська функція та джерело помилок.
Не зрозумійте мене неправильно, може бути скрізь кілька сімей функцій, що воюють за цю структуру даних зі снопами, покроковими шубами та подвійними агентами. Добре, коли у кожного є своя структура даних, з якою вони можуть грати, але коли вони діляться ними ... тільки уявіть, як кілька злочинних сімей не погоджуються з приводу політики, це може швидко стати безладом.
Враховуючи, що сім'ї розширених функцій безладу можуть досягти, чи існує спосіб кодування структури даних, щоб недобросовісні функції не зіпсували все? Так, їх називають Об'єкти.
Чи корисні геттери / сетери в об’єктах? Ні.
Весь сенс загортання структури даних в об’єкт полягав у тому, щоб переконатися у відсутності функцій шахраїв. Якщо функція хотіла приєднатися до сім’ї, її потрібно було спочатку ретельно перевірити, а потім стати частиною об’єкта.
Точка / мета геттера та сеттера полягає в тому, щоб дозволити функціям, що знаходяться поза об'єктом, безпосередньо змінювати компонування пам'яті об'єкта. Це звучить як відкриті двері, щоб пускати в шахраїв ...
Справа "Край"
Існують дві ситуації, коли громадські організації, які отримують геттер / сеттерів, мають сенс
- Частина структури даних всередині об'єкта управляється об'єктом, але не контролюється об'єктом.
- Інтерфейс, що описує абстрагування структури даних на високому рівні, де, як очікується, деякі елементи не будуть контролювати об'єкт, що реалізує.
Контейнери та інтерфейси контейнерів - прекрасні приклади обох цих двох ситуацій. Контейнер керує структурами даних (пов'язаний список, карта, дерево) внутрішньо, але передає контроль над певним елементом для всіх та різних. Інтерфейс резюмує це і повністю ігнорує реалізацію та описує лише очікування.
На жаль, багато реалізацій помиляються і визначають інтерфейс подібних об'єктів для прямого доступу до фактичного об'єкта. Щось на зразок:
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);
}
Це порушено. Реалізації Container повинні явно передавати контроль над їх внутрішніми послугами тим, хто їх використовує. Я ще не бачив мови з змінним значенням, де це добре (мови з семантикою незмінного значення за визначенням є чіткими з точки зору корупції даних, але не обов'язково з точки зору шпигування даних).
Ви можете вдосконалити / виправити getters / setter, використовуючи лише копію семантику або за допомогою проксі:
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
викличете проблеми.