Навіщо нам потрібні приватні змінні?


210

Навіщо нам потрібні приватні змінні в класах?

Кожна прочитана книга з програмування говорить, що це приватна змінна, саме так ви її визначаєте, але зупиняється на цьому.

Формулювання цих пояснень мені завжди здавалося так, ніби ми справді маємо кризу довіри до своєї професії. Пояснення завжди звучали так, ніби інші програмісти зіпсують наш код. Однак існує багато мов програмування, які не мають приватних змінних.

  1. Що приватні змінні допомагають запобігти?

  2. Як ви вирішите, чи має бути певна власність приватною чи ні? Якщо за замовчуванням кожне поле ОБОВ'ЯЗКОВО бути приватним, то чому в класі є учасники загальнодоступних даних?

  3. За яких обставин слід оприлюднювати змінну?


9
Ваше запитання звучить дуже мовно-агностично, але ви позначили його як java та c ++. Якщо вас цікавлять перспективи, що знаходяться поза цими двома мовами, ви, ймовірно, повинні так сказати.
Джеймс

8
Для запису, створення приватного методу не підвищує "безпеку". Інші частини вашої програми все ще можуть отримати доступ до приватних членів за допомогою роздумів.
kba

3
Використання та відмінність приватних та загальнодоступних змінних, і чому ми їх маємо, можна зрозуміти лише в контексті загальних об'єктно-орієнтованих принципів. Це не можна зрозуміти окремо. Вам, мабуть, потрібно подивитися на це з тієї точки зору, все може стати зрозумілішим.
Назар Мерза

1
можливий дублікат " Коли виправдані
геттери

3
Якщо ви зловили когось, хто використовує ремінь безпеки в своєму автомобілі, вам слід забрати їх посвідчення водія, оскільки, очевидно, вони не довіряють власним можливостям керувати автомобілем.
gnasher729

Відповіді:


307

Це не стільки питання довіри, скільки швидше управління складністю.

Доступ до публічного члена можна отримати поза класом, що з практичних міркувань означає «потенційно де завгодно». Якщо з громадським полем щось піде не так, винуватцем може бути де завгодно, і тому для того, щоб відшукати помилку, можливо, доведеться переглянути досить багато коду.

Навпаки, до приватного члена можна отримати доступ лише з одного класу, тому якщо щось із цим піде не так, зазвичай слід переглянути лише один вихідний файл. Якщо у вашому проекті є мільйон рядків коду, але ваші заняття залишаються невеликими, це може зменшити ваші зусилля відслідковування помилок в 1000 разів.

Ще одна перевага пов'язана з поняттям "з'єднання". Громадський член mкласу , Aякий використовується іншим клас Bвводить залежність: якщо ви зміните mв A, ви також повинні перевірити використання mв B. Що ще гірше, ніщо в класі не Aпідкаже, де mвикористовується, тому знову доведеться шукати всю базу коду; якщо це бібліотека, яку ви пишете, вам навіть доведеться переконатися, що код зовніваш проект не порушується через вашу зміну. На практиці бібліотеки прагнуть дотримуватися підписів оригінальних методів якомога довше, як би не було болісно, ​​а потім впроваджують блок розривів змін за допомогою основного оновлення версії. З приватними членами, навпаки, ви можете виключати залежності відразу - вони не можуть бути доступні зовні, тому всі залежності містяться всередині класу.

У цьому контексті "інші програмісти" включають ваше майбутнє та минуле "я". Можливо, ви знаєте, що зараз не слід робити цю справу X зі своєю змінною Y, але ви, мабуть, забули три місяці в дорозі, коли клієнту терміново потрібно, щоб ви застосували якусь функцію, і вам цікаво, чому робити X перерви Y незрозумілими способами.

Отже, що стосується того, коли слід робити речі приватними: я б сказав, що все стане приватним за замовчуванням, а потім викрийте лише ті частини, які абсолютно повинні бути публічними. Чим більше можна зробити приватним, тим краще.


24
+1 для отримання основи проблеми, хоча я особисто знайшов свій код простішим у обслуговуванні, коли перестав обробляти обручі лише для того, щоб часто використовувана змінна залишалася приватною. Звичайно, в майбутньому може виникнути помилка, але це потрібно на 60 менше рядків коду, які потрібно просіяти, і менше змінних та функцій для завантаження;)
Джеффрі Свіні

48
Святий граал сучасних обчислень зменшує складність.

1
Мені завжди хотілося б сказати, що частина налагодження - це не просто рух безпосередньо до того, "що пішло не так", а взяття на круговий процес з'ясування "чого не пішло не так", а також зосередження мого розслідування на тому, що залишилося. Якщо я можу домогтися компілятора, щоб допомогти мені за допомогою таких інструментів, як приватні змінні, щоб визначити, "чого не могло статися", це економить мені час. Тільки в тих рідкісних випадках, коли я доводжу, що те, що пішло не так, не могло статися, мені доводиться розбиратися в більш страхітливих припущеннях, як, можливо, переповнення буфера, що переписує мої приватні дані.
Корт Аммон

2
Саме так. Коли люди чують "приховування інформації", вони думають, що їм слід користуватися приватними змінними для таких речей, як ключі шифрування, облікові дані бази даних тощо
Wayne Werner

2
@AdamZerner див. "Скажіть, не запитуйте" ( martinfowler.com/bliki/TellDontAsk.html ) про те, щоб на першому місці були геттери / сетери, але в іншому випадку - так, тому що ви повинні вільно змінювати внутрішнє представлення значення у будь-який час ти бажаєш. Як завжди, є винятки ... (наприклад, DTO)
подвійно

111

Приватні змінні допомагають заважати людям залежно від певних частин вашого коду. Наприклад, скажіть, що ви хочете реалізувати певну структуру даних. Ви хочете, щоб користувачі вашої структури даних не хвилювались, як ви її реалізували, а скоріше просто використовувати її через ваш чітко визначений інтерфейс. Причина полягає в тому, що якщо ніхто не залежить від вашої реалізації, ви можете змінювати її коли завгодно. Наприклад, ви можете змінити допоміжну реалізацію для покращення продуктивності. Будь-які інші розробники, які залежать від вашої реалізації, зламаються, тоді як користувачі інтерфейсу будуть добре. Наявність гнучкості змінювати реалізацію, не впливаючи на користувачів класу, є величезною перевагою, яку дає вам використання приватних змінних (і в більш широкому сенсі, інкапсуляція ).

Також насправді це не «криза довіри». Якщо ви оприлюднили частину даних, ви не можете забезпечити, щоб ніхто не залежав від них. Часто дуже зручно залежати від певної змінної, що стосується впровадження, замість того, щоб переглядати загальнодоступний інтерфейс, особливо в розпал терміну. Крім того, розробники не завжди розуміють, що вони залежать від того, що може змінитися.

Тож цей варіант відповідає на ваші інші запитання, сподіваюся. Усі деталі вашої реалізації повинні бути приватними, а публічна частина повинна бути невеликим, стислим, чітко визначеним інтерфейсом для використання вашого класу.


24
IMO також стосується спілкування між автором lib та споживачем lib. Публічний інтерфейс схожий на "користуйся цим", а приватні особи схожі на "не користуйся цим", за винятком того, що на Яві ви справді не можете використовувати його випадково, якщо зробити його приватним, щоб це було більш безпечним і зрозумілим.
чакрит

5
@chakrit та інші. Зауважте, що ті, хто насправді не користується вашими приватними полями та методами, можуть це зробити (за допомогою роздумів). privateменше, ніж "не в першу чергу призначене для безпеки", воно не забезпечує ніякої "безпеки". Це просто сильна підказка (доставлена ​​через компілятор) не мати доступу до неї.

@delnan відзначте фразу "випадково", так, можливо, я повинен бути більш чітким щодо цього.
чакрит

@chakrit Так, я не мав на увазі, що ти помилявся. Я просто хотів просувати цю точку.

1
@delnan: Приватні поля в деяких мовах забезпечують певні форми захисту. Наприклад, див. Відповідь Еріка Ліпперта на те, чи служать рівні доступу та модифікатори (приватні, запечатані тощо) цілям безпеки в C #? .
Брайан

25

Ключове слово тут - інкапсуляція . В OOP ви хочете використовувати приватні змінні, щоб забезпечити належну інкапсуляцію ваших об'єктів / класів.

Хоча інші програмісти не хочуть вас отримати, вони взаємодіють з вашим кодом. Якщо ви не зробите приватну змінну, вони можуть посилатися на неї у власному коді, не бажаючи взагалі завдати шкоди. Однак якщо вам потрібно повернутися до свого класу та щось змінити, ви більше не знаєте, хто використовує, яка змінна та де. Мета інкапсуляції - зробити зовнішній інтерфейс класу явним, щоб ви знали, що лише ці (зазвичай) методи могли бути використані іншими.

  1. Отже, приватні змінні гарантують, що відповідна змінна залишається лише у визначеному класі. Якщо вам потрібно змінити, зміна є локальною для самого класу.

  2. У традиційних робочих місцях, таких як C ++ або Java, ви зазвичай робите все приватним і доступним лише відповідним геттерам і сетерам. Не потрібно дуже багато вирішувати.

  3. Іноді, f.ex. у структурі C ++ вам потрібен клас лише як спосіб згрупувати кілька речей разом. Наприклад, розглянемо векторний клас, у якого є xлише yатрибут та атрибут. У цих випадках ви можете дозволити прямий доступ до цих атрибутів, оголосивши їх загальнодоступними. Зокрема, вам не варто байдуже, чи якийсь код зовні модифікує об’єкт вашого класу, безпосередньо записуючи нові значення в xабо y.

В якості додаткового моменту зауважте, що в інших мовах це питання розглядається дещо по-іншому. Наприклад, мови, сильно укорінені у функціональному програмуванні, підкреслюють незмінність даних, тобто значення даних взагалі не можуть бути змінені. У таких випадках не потрібно дбати про те, що інші програмісти (а точніше їх код) роблять з вашими даними. Вони просто не можуть зробити нічого, що може вплинути на ваш код, оскільки всі дані незмінні.

Таким чином, у цих мовах ви отримуєте щось, що називається єдиним принципом доступу , де навмисно не розрізняють способи, такі як геттери та сеттери, але забезпечують прямий доступ до змінної / функції. Тож ви можете сказати, що приватні декларації є набагато популярнішими в об'єктно-орієнтованих сценаріях.

Це також показує, як розширення ваших знань на інші поля змушує переглядати існуючі концепції абсолютно по-новому.


1
+1 "Хоча інші програмісти не хочуть вас отримати, вони взаємодіють з вашим кодом." Програмістам, які використовують ваш код, не властиво зло. Використовуючи приватні змінні, ви переконайтеся, що вони (і ви, в майбутньому) не пошкодитесь, використовуючи код. Це також допомагає вам розробити кращий API та документувати його.
szalski

7

Приватні змінні гарантують, що більш пізні посилання, що виходять за межі об'єкта чи функції, ненавмисно не впливають на інші змінні. Для великих програм програмування це може допомогти уникнути безлічі цікавих проблем (які зазвичай не потрапляють компілятором).

Наприклад, прототипічні мови, такі як Javascript, можуть дозволити користувачам пластувати змінні, як вони вважають за потрібне:

function SomeObject() {
    this.a = 2; //Public (well, actually protected) variable

    this.showA = function() {
        alert(this.a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 3. Uh oh!

Якщо ця змінна була приватною, її не можна було б змінити ззовні:

function SomeObject() {
    var a = 2; //Private variable

    this.showA = function() {
        alert(a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 2

Однак, не всі змінні повинні бути приватними, а надмірне використання приватних змінних насправді може зробити код більш громіздким. Тривіальні поля, які серйозно не впливають на об’єкт, не потребують get()і set()методи.

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

Загальнодоступні змінні слід використовувати, коли об’єкт / функція матиме доступ до інших об'єктів / функцій, оскільки, як правило, приватні змінні не можуть цього зробити. Можливо, у вас є десь від кількох до зовсім небагато загальнодоступних змінних, і не погано їх використовувати, якщо вони використовуються правильно.


Не очевидно, чому оповіщення 3 буде "е-о-о!" в цьому випадку. Можливо, саме так хотів статися програміст.
іммібіс

@immibis Можливо, і, можливо, я повинен був би детальніше розказати у відповіді. Але доступ до властивостей може відкрити двері для порушення деяких принципів OOP, таких як принцип відкритого закриття або LoD, оскільки ви потенційно розкриваєте деталі реалізації. "Звичайно, це залежить від того, яка саме власність. Більшість мов використовують об'єкти в якості посилань, і коли посилання на об'єкти передаються навколо, а колеги дивовижники спокійно змінюють властивості, це дуже СЛОВО можна налагодити. ІМО набагато простіше і розширювати роботу з методами, якщо у вас є екземпляр класу.
Джефрі Свіні

7

Є кілька хороших відповідей із посиланням на переваги для майбутніх керівників та користувачів класу. Однак є і переваги оригінального дизайну. Він забезпечує чітку розмежувальну точку між тим, коли ваша мета - полегшити справи на собі, і коли ваша мета - полегшити справи користувачеві класу. Коли ви вибираєте між державним і приватним, він сигналізує вашому мозку перейти в той чи інший режим, і ви отримаєте кращий API.

Справа не в тому, що мови без конфіденційності роблять такий дизайн неможливим, лише менш імовірним. Замість того, щоб вас запросили написати щось подібне foo.getBar(), люди схильні думати, що геттер не потрібен, тому що писати простіше foo.bar, але тоді це рішення не переглядається, коли згодом ви закінчитеся з більш довгими жахливими явищами obj.container[baz].foo.bar. Програмісти, які ніколи не працювали більш суворою мовою, можуть навіть не бачити, що в цьому погано.

Ось чому в мовах без конфіденційності люди часто прийматимуть стандарти іменування, що їх моделюють, наприклад, попереджуючи підкреслення всіх "приватних" членів. Це корисний сигнал, навіть коли мова не застосовує його.


3

Усі змінні повинні бути приватними, за винятком випадків, коли вони абсолютно не повинні бути загальнодоступними (що майже ніколи не слід використовувати властивості / getters та setters).

Змінні значною мірою забезпечують стан об'єкта, а приватні змінні заважають іншим входити та змінювати стан об'єкта.


5
Занадто вузький погляд на предмет. Бувають випадки, коли доступ до публічного поля є гарантованим, навіть кращим
Roland Tepp

Безумовно, можна проектувати об’єкти, стан яких неможливо змінити (незмінні об'єкти), але це не загальне правило, що застосовується до всіх класів. На мій досвід, більшість об'єктів дуже легко змінюють стан об'єкта для інших.
Девід К

1
@DavidK Можливо, це означає, що bbb мав на увазі те, що "приватні змінні заважають іншим входити і без розбору змінювати стан об'єкта". Публічні методи можуть змінювати приватний стан об'єкта, але лише способами, необхідними та послідовними для функціонування об'єкта.
Макс Нанасі

@Max Nanasy: Так, можна контролювати, як змінюється стан, коли пропонуються лише методи в публічному інтерфейсі. Наприклад, між членами може виникнути взаємозв'язок, який повинен бути задоволений, щоб об'єкт був "самовідповідним", і ви могли б дозволити зміну стану, що відповідає самопослідовності, лише на інший самопослідовий стан. Якщо всі ці змінні є загальнодоступними, ви не можете цього застосувати. Але також можуть бути об’єкти, про які ви не хочете допускати жодних змін, тому важливо уточнити, про які з цих речей ми говоримо.
Девід К

2
  • Що приватні змінні допомагають запобігти?

Йдеться про те, щоб зрозуміти, які властивості та методи є інтерфейсом, а які - насправді основними функціональними можливостями. Публічні методи / властивості стосуються іншого коду, часто іншого коду розробника з використанням ваших об'єктів. Я ніколи не працював над командами по 100+ над тим самим проектом, але, на моєму досвіді, можливо, команди з 3-5 осіб, що містять до 20 інших розробників, які використовують речі, про які я написав, інші проблеми здаються дурними.

Примітка. Я насамперед розробник JavaScript. Я взагалі не переживаю, щоб інші розробники переглядали мій код, і я працюю з цілком усвідомленою інформацією, що вони можуть просто переробити мої речі в будь-який час. Я припускаю, що вони досить компетентні, щоб знати, що вони роблять першими. Якщо ні, то навряд чи я працюю над командою, яка не використовує керування джерелами.

  • Як ви вирішите, чи повинен певний набір властивостей бути приватним чи ні? Якщо за замовчуванням кожне поле ОБОВ'ЯЗКОВО бути приватним, то чому в класі є учасники загальнодоступних даних?

Я думав, що нерозумно було розміщувати гетерів та сеттерів на приватних об'єктах, коли ви насправді не виконували жодної перевірки чи іншого спеціального режиму майна, яке буде встановлено. Я все ще не думаю, що це завжди потрібно, але коли ти маєш справу з великими масштабами, високою складністю, але найголовніше багато інших дияволів, які покладаються на те, що твої об'єкти поводяться послідовно, може бути корисно робити речі в послідовний і рівномірний спосіб. Коли люди бачать методи, що називаються getThatіsetThat, вони точно знають, які наміри, і можуть написати свої об'єкти, щоб взаємодіяти з вашими, сподіваючись, що вони завжди отримають помідори, а не томахто. Якщо вони цього не роблять, вони знають, що ваш об’єкт дає їм щось, що, мабуть, не повинно, а це означає, що це дозволяє іншому об'єкту щось робити з цими даними, він, мабуть, не повинен. Ви можете це контролювати в міру виникнення потреби.

Інша велика перевага полягає в тому, що простіше, щоб ваші об'єкти передавали або інтерпретували значення по-різному від геттера або сеттера на основі якогось різного контексту стану. Оскільки вони отримують доступ до ваших матеріалів методом, набагато простіше змінити, як ваш об’єкт працює згодом, не порушуючи іншого коду, який від нього залежить. Важливим принципом є те, що лише ваш об’єкт фактично змінює дані, за які ви його зробили відповідальними. Це особливо важливо для збереження вашого коду вільно поєднаним, що є величезною виграшею з точки зору портативності та простоти модифікації.

  • За яких обставин слід оприлюднювати змінну?

Завдяки функціям першого класу (ви можете передавати функції в якості аргументів), я не можу придумати безліч чудових причин, крім того, що це не дуже важливо для цього в менших масштабах проектів. Без цього, я думаю, у вас можуть бути члени, які інтенсивно та регулярно обробляються іншими об’єктами, настільки, що здається трохи важким, щоб постійно отримувати дзвінки і встановлювати об'єкт, який насправді не торкається цих даних, але це в Сам би змусив мене замислитися, чому об’єкт відповідав за ці дані. Взагалі кажучи, я б схильний хотіти переглядати мою архітектуру на наявність недоліків, перш ніж приймати рішення про власність загальнодоступних даних. IMO, нічого поганого в тому, що мова дозволяє вам робити щось, що зазвичай є поганою ідеєю. Деякі мови не згодні.


ІМХО, немає нічого особливо поганого в тому, щоб мати публічний клас, єдиною метою якого є викриття публічних змінних. У самому справі, віртуальна машина має ряд вбудованих класів для цієї мети: int[], double[], Object[]і т.д. Слід, однак, бути дуже обережним про те , як один виставляють екземпляри такого класу. Сенс void CopyLocationTo(Point p);[прийняття Pointвід абонента] зрозуміліший Point location(), оскільки незрозуміло, який вплив Point pt = foo.location(); pt.x ++;матиме місце розташування foo.
supercat

2

Дивіться цей мій пост у спорідненому запитанні про SO .

Недолік цього полягає в тому, що змінна область застосування дозволяє показувати споживачам свого коду те, що вони повинні і з чим не слід возитися. Приватна змінна може зберігати дані, які були "перевірені", використовуючи інструмент встановлення властивостей або метод обробки, щоб переконатися, що весь об'єкт знаходиться у постійному стані. Змінення значення приватної змінної безпосередньо може спричинити непослідовність об'єкта. Роблячи його приватним, хтось повинен працювати дуже важко і мати дійсно високі дозволи на виконання, щоб змінити його.

Таким чином, належне визначення розміру члена є ключовим фактором у самодокументуванні коду.


2

Я буду говорити про значення інкапсуляції з іншого погляду, використовуючи реальний приклад. Досить деякий час тому (на початку 80-х років) для радіо кольорового комп’ютера було написано гру під назвою Dungeons of Daggorath. Декілька років тому Річард Хунерлах переніс її із списку асемблерів паперу до C / C ++ ( http://mspencer.net/daggorath/dodpcp.html ). Через деякий час я отримав код і почав його повторно визначати, щоб покращити інкапсуляцію ( http://dbp-consulting.com/stuff/ ).

Код вже був врахований у різних об'єктах для обробки планування, відео, введення користувача, створення підземелля, монстрів тощо, але ви точно можете сказати, що він перенесений з асемблера. Моїм найбільшим завданням було збільшити інкапсуляцію. Під цим я маю на увазі дістати різні частини коду, щоб дістати собі ніс один до одного. Наприклад, було багато місць, які безпосередньо змінювали б змінні відео, щоб мати певний ефект. Деякі робили це за допомогою перевірки помилок, деякі ні, деякі мали дещо різні уявлення про те, що означає зміна цієї речі. Дублювання коду було дуже багато. Натомість у розділі відео потрібен інтерфейс для виконання бажаних завдань, а код для його виконання може бути все в одному місці, одна ідея, одне місце для налагодження. Така річ розгулувалась.

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

Все, що видно про ваш код, - це ваш інтерфейс. Чи ти маєш на увазі, чи є, чи ні. Якщо ви максимально обмежите видимість, пізніше ви не будете спокушатися поставити код у неправильному місці. Це дає зрозуміти, яка частина коду відповідає за які дані. Це робить кращий, чистіший, простіший, елегантніший дизайн.

Якщо ви зробите об'єкт, відповідальний за власні дані, і надайте інтерфейси всім іншим, для чого потрібно щось статися, ваш код стає ПРОСТО ПРОСТО. Це просто випадає. У вас є невеликі прості процедури, які виконують лише одне. Менша складність == менше помилок.


Жорсткий баланс між "свободою наших користувачів" та "меншими проблемами для нас". Я починаю вважати, що інкапсуляція краще в тому сенсі, що я запобігаю помилкам у власному кодуванні, і я допоможу кінцевим користувачам запобігти помилкам. Але відсутність свободи може просто позбавити їх, шукаючи альтернативи ... Можливо, кодування ще не використовується, але передбачені функціональні можливості за допомогою публічних методів можуть допомогти врівноважити це, але вимагає більше часу.
Сила Водолія

Шкода, що оновлена ​​версія не входить в github ....
jmoreno

2

Це не має нічого спільного з довірою чи страхом перед атаками, мова йде лише про інкапсуляцію - не змушувати зайвої інформації про користувача класу.

Розгляньте приватні константи - вони не повинні містити секретних значень (їх слід зберігати в іншому місці), їх неможливо змінити, їх не потрібно передавати у ваш клас (інакше вони повинні бути публічними). Єдине можливе використання для них як константи в інших класах. Але якщо ви це зробите, ці класи тепер залежать від вашого класу, щоб виконувати роботу, не пов’язану з вашим класом. Якщо ви змінюєте константу, інші класи можуть зламатися. Це погано з обох сторін - як письменник вашого класу, ви хочете, щоб свобода змінилася якомога більше, і не хочете турбуватися про речі, які не є вашими. Споживач вашого класу хоче мати можливість залежати від викритих деталей вашого класу, не турбуючись про те, щоб ви змінили його і не порушили його код.

Споживач вашого класу хоче знати все, що потрібно для ВЗАЄМОДІЇ з вашим класом, і не хоче нічого знати про ваш клас, що не змінює їхній спосіб: це марні дрібниці. Якщо ви використовували лангажу з відображенням, як часто ви використовували його для того, щоб дізнатись, як якийсь клас щось робить чи куди несподівано кидає виняток, а просто назву приватних полів та методів? Я ставлю ставку ніколи. Тому що ти не маєш користі для цих знань.


1

Концепція OOP має спадщину, має одну зі своїх особливостей (Java або C ++). Отже, якщо ми збираємося успадкувати (тобто ми отримаємо доступ до змінних спадкового класу), існує можливість впливати на ці змінні. Тому ми маємо вирішити, чи можна змінювати змінні чи ні.

Тільки для цієї мети ми використовуємо модифікатори доступу в OOP. Один з модифікаторів є приватним, що означає, що до нього можна отримати доступ лише цього класу. Будь-який інший клас не може впливати на ці змінні.

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

Чому в OOP існує концепція модифікатора, пояснюється цими причинами (будь-який клас може отримати доступ до інших змінних класів за допомогою концепції OOP). Якщо не існує концепції модифікаторів, це означає, що було б складно під час успадкування класів або використання інших концепцій OOP.


1

Як зазначають інші, приватні змінні добре уникати пропусків, що призводять об'єкт до непослідовного стану та важко відслідковувати помилки та непередбачувані винятки.

Але з іншого боку, те, що в основному ігнорували інші, стосується захищених полів.

Розширений підклас матиме повний доступ до захищених полів, що робить об'єкт таким тендітним, як ніби такі поля є загальнодоступними, але ця крихкість обмежується самим розширюваним класом (якщо він ще більше не відкрив такі поля).

Отже, загальнодоступні поля важко вважати хорошими, і на сьогоднішній день єдиною причиною їх використання є класи, які використовуються як параметр конфігурації (дуже простий клас з багатьма полями і без логіки, тому цей клас передається як параметр лише якийсь метод).

Але з іншого боку, приватні поля знижують гнучкість вашого коду для інших користувачів.

Гнучкість проти проблем, плюсів і мінусів:

Об'єкти, створені вашим кодом у класі ванілі із захищеними полями, є безпечними і ви несете виключну відповідальність.

З іншого боку, об’єкти, що розширюють ваш клас із захищеними полями, інстанційними користувачами вашого коду, є їх відповідальністю, а не вашою.

Отже, не добре задокументовані захищені поля / методи, або якщо користувачі не дуже розуміють, як такі поля та методи повинні використовуватися, мають хороші шанси завдати непотрібних неприємностей собі і вам.

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

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

Тепер вирішити питання між приватним та захищеним - справжня проблема.

Коли користуватися захищеним?

Щоразу, коли ви розумієте, поле може бути дуже гнучким, воно має бути закодовано як захищене. Ця гнучкість полягає: від того, щоб стати null (де null завжди перевіряється і визнається дійсним станом, не викидаючи винятки), до обмеження перед тим, як використовувати його клас вашого колишнього. > = 0, <100 і т.д.

Отже, для такого захищеного поля ви можете створити геттер і використовувати його тільки (замість прямого використання змінної поля), тоді як інші користувачі можуть не використовувати його, якщо вони хочуть більшої гнучкості до свого конкретного коду, у моєму прикладі це може бути : якщо вони хочуть, щоб негативні значення працювали нормально в розширеному класі.


-1

imo @tdammers неправий і насправді вводить в оману.

Приватні змінні існують, щоб приховати деталі реалізації. Можливо, ваш клас Aвикористовує arrayдля зберігання балів. Завтра ви можете скористатись treeабо priority queueзамість цього. Усі користувачі вашого класу потребують способу введення балів та імен addScore()та способу визначити, хто кращі 10 getTop(n).

Їм не потрібно отримувати доступ до основної структури даних. Звучить чудово? Ну, є деякі застереження.

У будь-якому випадку ви не повинні зберігати багато штатів, більшість із них не потрібні. Стан зберігання ускладнить ваш код навіть тоді, коли він "відокремлений" для певного класу. Подумайте, ця приватна змінна, ймовірно, змінилася, оскільки інший об'єкт називався методом цього класу. Вам все-таки потрібно розібратися, коли і де називався цей метод, і який публічний метод теоретично можна назвати будь-де.

Найкраще, що ви могли зробити, це обмежити кількість стану, яке містить ваша програма, і використовувати чисті функції, коли це можливо.


-1
  • Доступ до змінної середнього доступу до її значення під час запуску програми, що робить змінну приватною захищає її значення при запуску коду.
  • Сенс так званого "приховування даних" полягає в тому, щоб зберігати внутрішні дані, приховані від інших класів, які використовують клас. Ці інші класи повинні отримувати доступ до поведінки лише шляхом виклику методів у класі, а не шляхом прямого зміни значень змінних.
  • Зробивши змінну приватним учасником даних, ви можете легше переконатися, що значення ніколи не змінюється і не змінюється. З іншого боку, якщо змінна є загальнодоступною, інший клас може змінити або змінити значення, що може призвести до краху інших частин коду.

1
це, здається, не пропонує нічого суттєвого щодо пунктів, викладених та пояснених у попередніх 17 відповідях
грудок

-4

Спершу слід зрозуміти поняття об’єктно-орієнтованого програмування. Він має абстракцію, інкапсуляцію тощо.

Абстракція. Ви отримуєте уявлення про логіку без необхідності знати деталі реалізації.

Інкапсуляція - не можна побачити підкреслену реалізацію об’єкта. Тільки ви можете бачити загальнодоступний інтерфейс об'єкта.

Тепер у конкретній реалізації з однією з об'єктно-орієнтованих програм, таких як C #, Java, C ++, ви можете реалізувати ці концепції.

приватне - реалізація, яку слід приховувати від зовнішнього світу. Щоб ви могли змінити це, а користувач вашого класу не вплине на це.

public - це інтерфейс, за допомогою якого можна використовувати ваш об’єкт.


1
захищений - безпосередньо доступний підкласам (розширювачам) (java).
Сила Водолія
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.