Контакти

Який модифікатор доступу можна застосувати до пакета. Модифікатори доступу. Private, protected, default, public. Контроль доступу та успадкування

Тут ми намагатимемося розглянути майже всі випадки застосування модифікаторів доступу. Виняток становитимуть лише їх застосування для вкладених ( nested) та внутрішніх ( inner) класів, а також для інтерфейсів, оскільки ці теми ми поки що не розглядали.

Класи і пакети використовувані разом із модифікаторами доступу служать засобами інкапсуляції, тобто засобами приховування деталей реалізації за простим інтерфейсом.

Модифікатори доступу можуть застосовуватися як до класів, так і до їх членів – полів та методів. Усього існує чотири модифікатори доступу і тут наведемо їх короткий опис, потім розглянемо кожен докладно.

  • public– будь-який компонент, оголошений як public, доступний з будь-якого коду
  • protected– дозволяє доступ до компонента в межах пакету та класів спадкоємцям
  • private– дозволяє доступ до компонентів у межах класу
  • за замовчуванням(немає ключового слова) – дозволяє доступ до компонентів у межах пакета

Класи спадкоємці – це класи успадковані від будь-якого класу. Спадкування ми поки що не вивчали.

Доступ до класів

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

Доступ до членів класу

Члени класу завжди доступні усередині тіла класу. За замовчуваннямчлени класу також доступні у пакеті, в якому клас визначено.

Модифікатор

Для класу, що не є вкладеним, може бути вказано лише один із двох можливих рівнів доступу: заданий за замовчуваннямі public . Коли клас оголошений як public, він має бути єдиним publicкласом, оголошеним у файлі, та ім'я файлу має співпадати з ім'ям класу.

Як publicможуть бути оголошені класи, поля, методи та конструктори.

Модифікатор protected

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

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

Як protectedможуть бути оголошені поля, методи, конструктори, вкладені класи та вкладені інтерфейси.

protected .

Модифікатор private

Це найжорсткіший з обмеження доступу модифікатор. Елементи оголошені як privateдоступні тільки всередині цього ж класу і нікому поза класом.

Як privateможуть бути оголошені поля, методи, конструктори, вкладені класи та вкладені інтрефеси.

Класи та інтерфейси верхнього рівня не можуть бути оголошені як private .

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

Я створив класи Mod02.java, DefMod.java, ProMod.java та PrvMod.java які належать пакету pro.java.pkg002, а також клас PubMod.java, що належить пакету pro.java.pkg003. Далі наведу просто скріни цих класів та результат роботи програми:

Ми поговоримо про модифікатори: які бувають модифікатори, області видимості, модифікатори для класів, полів, методів. Думаю, буде не нудно.

Модифікатори в Java– це ключові слова, які надають класу, полю класу чи методу певних властивостей.

Для позначення видимості класу його методів та полів є 4 модифікатори доступу:

  • privateчлени класу доступні лише усередині класу;
  • package-private або default (за замовчуванням)члени класу видно усередині пакета;
  • protectedчлени класу доступні всередині пакету та у класах-спадкоємцях;
  • publicчлени класу доступні для всіх.

Якщо Ви пам'ятаєте, то в кінці, коли ми вже імпортували клас Cat, у нас все одно була помилка компіляції.

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

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

Уявіть, що у Вас є клас, який відображає об'єкт якогось продукту. Наприклад, машина. У машини може бути вартість. Ви створили поле ціна та ще безліч інших полів, купу методів, які відповідають за функціонал. Все начебто добре. Ваш клас машина є частиною величезного проекту і всі задоволені. Але припустимо, що хтось помилково або спеціально створив екземпляр класу автомобіль і поставив негативну ціну. Хіба може мати товар негативну ціну? Це дуже примітивний приклад і навряд чи таке може статися у реальному житті, але гадаю, ідея зрозуміла. Іноді потрібно дати доступ не безпосередньо, а через певні методи. Можливо, код відповідає за функціонал іншого коду, і Ви не хочете, щоб хтось змінював і редагував частину Вашого. Для цього і є обмеження доступу.

Модифікатор доступу у конструкторів, методів та полів може бути будь-яким. Клас може бути або public, або default, причому у одному файлі може бути лише одне public клас.

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

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

static модифікатор перед методом або полем говорить про те, що вони не належать до екземпляра цього класу. Що це для нас означає? Коли ми описали поле класу або метод як static, можна викликати без використання екземпляра класу. Тобто замість такої конструкції: Cat Cat = New Cat (); cat.method(), можна просто написати Cat.method(). За умови, що метод оголошений як static. Статичні змінні єдині всім об'єктів класу. Вони мають одне посилання.

    public class Modificators (

    static int anotherStaticField = 5;

    public static void myStaticMethod() (

    someField = "My field";

    //nonStaticField = ""; помилка компіляції

    //не можна використовувати нестатичні поля

    //в статичних методах

    public void myNonStaticMethod() (

    anotherStaticField = 4; //Ститичні поля можна використовувати

    //у нестатичних методах

    //main метод також має модифікатор static

    new Modificators() .myNonStaticMethod () ;

    Modificators.myStaticMethod(); //виклик статичних методів та полів

    //через ім'яКласа.метод

Ще одне важливе зауваження, яке слід сказати з приводу static модифікаторів: статичні поля ініціалізуються під час завантаження класу. Часто в різноманітних тестах з Java можна зустріти такий код:

Запитання: що буде виведено на консоль? Потрібно пам'ятати, що static блок буде виведений першим за будь-якого розкладу. Далі йтиме блок за замовчуванням. Далі дивіться на скрін консолі:

Наступний модифікатор, який ми розглянемо буде final.

Думаю, слово final каже саме за себе. Використовуючи final модифікатор Ви кажете, що поля не можуть бути змінені, методи перевизначені, а класи не можна успадковувати (про наслідування буде окрема стаття). Цей модифікатор застосовується тільки до класів, методів та змінних (також і до локальних змінних).

З модифікатором final до методів та класів ми говоритимемо у статті ООП.

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

Модифікатор synchronized- говорить про те, що метод може бути використаний лише одним потоком одночасно. Хоча, можливо, це Вам ні про що не говорить, корисність цього модифікатора буде видно, коли ми вивчатимемо багатопоточність.

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

Модифікатор volatile- Використовується при багатопоточності. Коли поле з модифікатором volatile буде використовуватися та змінюватись декількома потоками, даний модифікатор гарантує, що поле змінюватиметься по черзі та плутанини з ним не виникне.

Модифікатор nativeПеред оголошенням методу вказує, що метод написаний іншою мовою програмування. Зазвичай мовою C.

Модифікатор strictfp— Забезпечує виконання операцій над числами типу float і double (з плаваючою комою) за стандартом IEEE 754. Або простіше, гарантує що в межах методу результати обчислень будуть однаковими на всіх платформах.

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

Клас, який має модифікатор abstract, не може створити екземпляр. Єдина мета йому бути розширеним. Клас abstract може містити як абстрактні методи, так і звичайні.

Докладніше про модифікатора abstract говоритимемо у статті ООП.

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

Спочатку розберемося з модифікаторами доступу. Їх лише чотири:

  • privateчлени класу доступні лише всередині класу
  • package-private або default (за замовчуванням)члени класу видно всередині пакету
  • protectedчлени класу доступні всередині пакету та в класах-спадкоємцях
  • publicчлени класу доступні всім

Під час успадкування можлива зміна модифікаторів доступу до більшої видимості.

Модифікатор доступу у конструкторів, методів та полів може бути будь-який, а от із класами та їх блоками не так усе просто. Клас може бути або public, або default, причому у одному файлі може бути лише одне public клас. Блок може мати лише один модифікатор – default.

Модифікатори static, abstract та final

Static

  • Застосовується до внутрішніх класів, методів, змінних та логічних блоків.
  • Статичні змінні ініціалізуються під час завантаження класу
  • Статичні змінні єдині для всіх об'єктів класу (однакове посилання)
  • Статичні методи мають доступ тільки до статичних змінних
  • До статичним методам та змінним можна звертатися через ім'я класу
  • Статичні блоки виконуються під час завантаження класу
  • Не static методи не можуть бути перевизначені як static
  • Локальні змінні не можуть бути оголошені як static
  • Абстрактні методи не можуть бути static
  • Static поля не серіалізуються (тільки під час реалізації інтерфейсу Serializable)
  • Тільки static змінні класи можуть бути передані в конструктор з параметрами, що викликається через слово super(//параметр//) або this(//параметр//)

Abstract

  • Застосовується тільки для методів та класів
  • У абстрактних методів немає тіла методу
  • Є протилежністю final: final клас може успадковуватися, abstract клас повинен успадковуватися
  • Клас повинен бути оголошений як abstract якщо:
  1. він містить хоча б один абстрактний метод
  2. він не надає реалізацію наслідуваних абстрактних методів
  3. він не надає реалізацію методів інтерфейсу, реалізацію якого він оголосив
  4. необхідно заборонити створення екземплярів класу

Final

  • Поля не можуть бути змінені, методи перевизначені
  • Класи не можна успадковувати
  • Цей модифікатор застосовується тільки до класів, методів та змінних (також і до локальних змінних)
  • Аргументи методів, позначені як final, призначені лише для читання, при спробі зміни буде помилка компіляції
  • Змінні final не ініціалізуються за замовчуванням, їм необхідно явно надати значення при оголошенні або в конструкторі, інакше - помилка компіляції
  • Якщо final змінна містить посилання на об'єкт, об'єкт може бути змінений, але змінна завжди буде посилатися на той самий об'єкт
  • Також це справедливо і для масивів, тому що масиви є об'єктами, – масив може бути змінений, а змінна завжди посилатиметься на той самий масив.
  • Якщо клас оголошений final і abstract (взаємовиключні поняття), буде помилка компіляції
  • Так як final клас не може успадковуватись, його методи ніколи не можуть бути перевизначені
Конструкторне може бути static, abstract або final

Модифікатори strictfp, transient, volatile, synchronized, native

Strictfp

  • Застосовується для методів та класів
  • Забезпечує виконання операцій над числами типу float та double (з плаваючою комою) за стандартом IEEE 754

Transient

  • Застосовується тільки для змінних рівня класу (локальні змінні не можуть бути оголошені як transient)
  • Перехідніперемінні можуть не бути final або static.
  • Transientзмінні не серіалізуються

Volatile

  • Використовується лише зі змінними
  • Може використовуватися зі static змінними
  • Не використовується з final змінними - значення змінної, оголошеної як volatile, змінене одним потоком, асинхронно змінюється і для інших потоків
  • Застосовується в багатопотокових додатках

Synchronized

  • Застосовується тільки до методів або частин методів
  • Використовується для контролю доступу до важливих частин коду в багатопотокових програмах.

Native

  • Використовується лише для методів
  • Позначає, що метод написаний іншою мовою програмування
  • Класи в Java використовують багато native методів для підвищення продуктивності та доступу до апаратних засобів
  • Можна передавати/повертати Java об'єкти з методів native
  • Сигнатура методу має закінчуватися “;”, фігурні дужки спричинять помилку компіляції

Особливості в інтерфейсах

  • Методи завжди public і abstract, навіть якщо це не оголошено
  • Методи не можуть бути static, final, strictfp, native, private, protected
  • Змінні тільки public static final, навіть якщо це не оголошено
  • Змінні не можуть бути strictfp, native, private, protected
  • Може лише успадковувати (extends) інший інтерфейс, але з реалізовувати інтерфейс чи клас (implements).

Зберемо всі модифікатори разом:

Клас

Внутрішній клас

Змінна

Метод

Конструктор

Логічний блок

public

Так

Так

Так

Так

Так

Ні

protected

Ні

Так (крім локальних та анонімних класів)

Так

Так

Так

Ні

default

Так

Так

Так

Так

Так

private

Ні

Так (крім локальних та анонімних класів)

Так

Так

Так

Ні

final

Так

Так (і для локальної змінної)

Так

Ні

Ні

abstract

Так

Так (крім анонімних класів)

Ні

Так

Ні

Ні

static

Ні

Так (крім локальних та анонімних класів)

Так

Так

Ні

Так

native

Ні

Ні

Ні

Так

Ні

Ні

transient

Ні

Ні

Так

Ні

Ні

Ні

synchronized

Ні

Ні

Ні

Так

Ні

Так (тільки частина методу)

volatile

Ні

Ні

Так

Ні

Ні

Ні

strictfp

Так

Так

Ні

Так

Ні

Ні

5

Я бачив деякі дискусії в StackOverflow на цю тему, але я не бачу щось, що допомогло мені зрозуміти наступний пункт:

я походжу з фону C++ і останнім часом Я почав вивчати Java. У C++, коли захищений, використовується лише підклас, який може отримати доступ до члена (аналог поля Java).

C++ також має класи «друг», які можуть мати доступ до приватних/захищених камер класу, які дають «дружбу». Це трохи схоже на модифікатор поля «package» в Java (модифікатор поля за замовчуванням), за винятком того, що C++ дружба дає доступ до всіх закритих членів, але в Java доступ з класів в одному пакеті специфічний для поля класу,

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

Але на Java я не знаю, як це зробити, оскільки за допомогою «захищеного» модифікатора поля – я також надаю доступ до всіх класів у пакеті. Єдиний спосіб, яким я знаходжу це, – оголосити захищене поле та ізолювати клас у своєму пакеті.

Звідси я укладаю, що угруповання класів в один пакет має виконуватись на основі «дружби» між класами. Чи це є провідним фактором при групуванні пакетів?

Ще одна річ, яку я не розумію, в Java, припускаючи, що я маю два поля в класі A: b, c. Я хочу дати B доступ до b, але не, і я хочу дати C доступ до c, але не b. і до "Світу" я хочу b, c, щоб приховати. Як це можна зробити? Я припускаю, що B, C повинні бути в тому ж пакеті, що і A. але шляхом оголошення b, c з пакетоммодифікатором Я дозволяю B, C доступ як до, так і до. Чи є спосіб Java, щоб це зробити?

Надія на деяке пояснення цього питання

11

Найкраще питання, якщо менш корисним для вас буде більш вузьким та конкретним. Загальне питання «все про конфіденційність у Java і C++ і про те, як вони відрізняються», більш ніж дуже широке. Чи можете ви поставити більш конкретне питання про конкретнішу проблему? - Yakk 04 бер. 15 2015-03-04 16:38:58

  • 4 відповіді
  • Сортування:

    Активність

2

У C++, коли використовується захист, тільки підклас може отримати доступ до елемента (аналог поля Java).

Специфікатори доступу також призначені для функцій-членів/методів, а не лише для змінних-членів.

У C++ є також «друг» класи, які можуть мати доступ до приватних/захищаються mambers класу, що дає «дружбу». Цей трохи схожий на модифікатор поля "package" в Java (за замовчуванням модифікатор поля), за винятком того, що в C++ дружба дає доступ до всіх приватних членів, але Java доступ з класів в тому ж пакеті специфічний для поля класу.

Існує не тільки friend класи, але й функції.

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

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

Але в Java, я не знаю, як я можу це зробити,

Відповідь: Ви не можете.

оскільки за допомогою «захищеного» модифікатора поля – я також надаю доступ до всіх класів у пакеті.

Єдиний спосіб, яким я знаходжу, це оголосити захищене поле та мати клас ізольований у його пакеті.

Технічно, так. Але це створює інші проблеми. Ваш клас не зможе отримати доступ до приватних частин пакета свого попереднього пакета. Допустимо, ваш BaseClass був у com.example.one . Ви перемістите його на com.example.two. Тепер він більше не зможе отримати доступ до інших пакетів-приватних класів com.example.one.

Чи це є провідним фактором при групуванні пакетів?

Так, Java спроектований таким чином. Ви можете спробувати боротися із правилами мовиале це програшна битва будь-якою мовою програмування.

Ще одна річ, яку я не розумію, в Java, припускаючи, що я маю два поля в класі A: b, c. Я хочу дати B доступ до b, але не, і я хочу надати C доступ до c, але не b. і в "Світ" я хочу b, c, щоб приховати. Як це можна зробити?

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

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

1

Це досить купа питань разом...

Але в Java, я не знаю, як я можу це зробити, тому що в силу використовуючи "захищений" модифікатор поля - я також надаю доступ до всіх класів у пакеті.

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

Єдиний спосіб, яким я знаходжу це, – оголосити захищене поле та ізолювати його у своєму пакеті.

Це технічно правильно, хоча це мало використовуватиме. Упаковка класів призначена для угруповання пов'язаних класів, де «споріднені» означає «класи, які виконують конкретне ставлення», тобто. сутності і т.д.

Звідси я укладаю, що угруповання класів в один пакет має виконуватись на основі «дружби» між класами. Чи це є провідним фактором при групуванні пакетів?

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

Для вашого A, B та C класів, наприклад, з атрибутами:

Я думаю, B, C має бути як у тому ж пакеті, А. а оголошує б, з модифікатором упаковки I нехай, C доступ як до b, так і до. Чи є спосіб в Java зробити це?

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

0

Коротка відповідь: немає жодного способу зробити це.

Якщо ви турбуєтеся про вторгнення від клієнтів ін'єкційного класу в пакеті, щоб отримати несанкціонований доступ, ви можете переміщати чутливий код в окремому пакеті, і зробити пакет запечатаного в банку ви доставити його до: http://docs.oracle.com/javase/tutorial /deployment/jar/sealman.html

1

Неявно передбачається, що всі класи в пакеті «знають» один одного (бо вони були написані однією і тією ж особою/компанією/організацією). Таким чином, вони або не отримують доступу до полів protected , або якщо вони це роблять, вони знають, як це зробити належним чином.

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

Отже, я думаю, вам не варто перейматися тим, як класи в одному пакеті можуть звертатися до полів один одного. Загалом, я просто не використовую цю функцію, крім випадків, коли я пишу ітератори.

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

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

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

Public class A ( public static abstract class B ( protected Whatever getWhatever(A a) ( return ab; ) protected void setWhatever(A a, Whatever value) ( ​​ab = value; ) ) public static abstract class C ( protected Whatever getWhatever(A a) ( return ac; ) protected void setWhatever(A a, Whatever value) ( ​​ac = value; ) ) private Whatever b; private Whatever c;

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

Останнє оновлення: 03.10.2019

Усі члени класу – поля, методи, властивості – всі вони мають модифікатори доступу. Модифікатори доступу дозволяють встановити допустиму область видимості для членів класу. Тобто модифікатори доступу визначають контекст, у якому можна використовувати цю змінну чи спосіб. У попередніх темах ми з ним зіштовхувалися, коли оголошували поля класу публічними (тобто з модифікатором public).

C# застосовуються наступні модифікатори доступу:

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

    private: закритий клас або член класу. Представляє повну протилежність модифікатору public. Такий закритий клас або член класу доступний тільки з коду того ж класу або контексті.

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

    internal : клас і члени класу з подібним модифікатором доступні з будь-якого місця коду в тій самій збірці, однак він недоступний для інших програм та збірок (як у випадку з модифікатором public).

    protected internal : поєднує функціонал двох модифікаторів. Класи та члени класу з таким модифікатором доступні з поточної збірки та похідних класів.

    private protected : такий член класу доступний з будь-якого місця в поточному класі або похідних класах, визначених у тій же збірці.

Ми можемо явно встановити модифікатор доступу, наприклад:

Private protected class State ( internal int a; protected void Print() ( Console.WriteLine($"a = (a)"); ) )

Або можемо не вказувати:

Class State ( int a; void Print() ( Console.WriteLine($"a = (a)"); ) )

Якщо для полів і методів не визначено модифікатор доступу, то для них застосовується модифікатор private .

Класи і структури, оголошені без модифікатора, мають доступ до internal .

Усі класи та структури, визначені безпосередньо у просторах імен і які є вкладеними інші класи, можуть мати лише модифікатори public чи internal.

Подивимося на прикладі та створимо наступний клас State:

Public class State ( // все одно, що private int defaultVar; int defaultVar; // поле доступне тільки з поточного класу private int privateVar; // доступно з поточного класу та похідних класів, які визначені в цьому ж проекті protected private int protectedPrivateVar; // доступно з поточного класу та похідних класів protected int protectedVar;// доступно в будь-якому місці поточного проекту internal int internalVar; будь-якому місці програми, а також для інших програм і збірок public int publicVar;// за замовчуванням має модифікатор private void defaultMethod() => Console.WriteLine($"defaultVar = (defaultVar)"); private void privateMethod() => Console.WriteLine($"privateVar = (privateVar)");// доступний з поточного класу та похідних класів, які визначені в цьому ж п роекті protected private void protectedPrivateMethod() => Console.WriteLine($"protectedPrivateVar = (protectedPrivateVar)"); // доступний з поточного класу та похідних класів protected void protectedMethod()=> Console.WriteLine($"protectedVar = (protectedVar)"); // доступний будь-де поточного проекту internal void internalMethod() => Console.WriteLine($"internalVar = (internalVar)"); // доступний у будь-якому місці поточного проекту та з класів-спадкоємців в інших проектах protected internal void protectedInternalMethod() => Console.WriteLine($"protectedInternalVar = (protectedInternalVar)"); // доступний у будь-якому місці програми, а також для інших програм та складання public void publicMethod() => Console.WriteLine($"publicVar = (publicVar)"); )

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

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

Тепер подивимося, як ми зможемо використовувати змінні нашого класу в програмі (тобто в методі Main класу Program), якщо класи State та Program знаходяться в одному проекті:

Class Program ( static void Main(string args) ( State state1 = new State(); // присвоїти значення змінної defaultVar у нас не вийде, // оскільки вона має модифікатор private і клас Program її не бачить // І цей рядок середа підкреслить як неправильну state1.defaultVar = 5; //Помилка, отримати доступ не можна // те саме відноситься і до змінної privateVar state1.privateVar = 5; // Помилка, отримати доступ не можна // присвоїти значення змінної protectedPrivateVar не вийде, // оскільки клас Program не є класом-спадкоємцем класу State state1.protectedPrivateVar =5; = 5;// Помилка, отримати доступ не можна // змінна internalVar з модифікатором internal доступна з будь-якого місця поточного проекту // тому спокійно надає їй значення state1.internalVar = 5; // змінна protectedInternalVar також доступна з будь-якого місця поточного проекту state1.protectedInternalVar = 5; // Змінна publicVar загальнодоступна state1.publicVar = 5; )

Таким чином, ми змогли встановити тільки змінні міжнародніVar, ProtectedInternalVar і publicVar, так як їх модифікатори дозволяють використовувати в даному контексті.

Аналогічно і з методами:

Class Program ( static void Main(string args) ( State state1 = new State(); state1.defaultMethod(); //Помилка, отримати доступ не можна state1.privateMethod(); // Помилка, отримати доступ не можна state1.protectedPrivateMethod() // Помилка, отримати доступ не можна state1.protectedMethod(); // Помилка, отримати доступ не можна state1.internalMethod(); // норм state1.protectedInternalMethod(); // норм state1.publicMethod(); // норм ) )

Тут нам виявилися доступні лише три методи: internalMethod, protectedInternalMethod, publicMethod, які мають відповідно модифікатори internal, protected internal, public.

Завдяки такій системі модифікаторів доступу можна приховувати деякі моменти реалізації класу з інших частин програми.

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



Сподобалась стаття? Поділіться їй