Чому клас не можна визначити як захищений?


89

Чому ми не можемо визначити клас як protected?

Я знаю, що ми не можемо, але чому? Повинна бути якась конкретна причина.


3
Що б це зробило , якщо б ви оголосили клас захищеним?

1
Я думаю , що це те , що ви шукаєте: stackoverflow.com/questions/2534733/java-protected-classes : D
dewijones92

2
Скажімо просто, чому зовнішній клас не можна захистити? Внутрішні класи можна захистити.
Номер 945

Відповіді:


101

Тому що це не має сенсу.

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

Однак ви можете оголосити вкладені та внутрішні класи захищеними або приватними.


> Оскільки в Java немає такого поняття, як "підпакет" або "успадкування пакетів", оголошення класу захищеним або пакет-приватним було б тим самим. Чому захищений клас мав би таку ж видимість, що і package-private? Хіба це не те саме, що публічне? Дякую.
yaromir

@Nikita Ryback Чи можете ви пояснити, що таке підпакет або успадкування пакета? Мені досі незрозуміло, чому захищений використовується в класі вищого рівня. Якщо ви пояснете на прикладі, це буде чудово.
App Kart

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

@kelgwiin Я вважаю, що вам не слід змішувати модифікатори доступу класів та членів. Тому що ці два різні. Хоча класи дозволяють змінювати себе як загальнодоступні або за замовчуванням, учасники можуть бути змінені як загальнодоступні, приватні, захищені та за замовчуванням.
sharhp

2
"Тому що це не має сенсу" - це досить сміливе твердження. Це не визначено в Java, але подібні речі дійсно існують; наприклад, openу Kotlin, який дозволяє підкласити поза поточним пакетом (можна було б уявити, що protectedJava запобігає цьому, з протилежним типом).
Рафаель

41

Як ви знаєте, за замовчуванням доступний для рівня пакету, а захищений - для рівня пакету плюс непакетні класи, але який розширює цей клас (Варто зазначити, що ви можете продовжувати клас, лише якщо він видимий!). Поставимо це так:

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

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


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


3

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

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

Отже, якщо «приватний клас foo» (визначено приватний член, тобто сам клас є членом) дозволяє, що таке зовнішній (який містить член)? Обсяг файлу? Ні, зовнішній файл безглуздий, оскільки навіть кілька класів в одному файлі будуть скомпільовані в окремі файли класів. Отже, зовнішній пакет . Але модифікатор доступу за замовчуванням 3-го рівня вже означає "приватний пакет ". Тож модифікатор приватного доступу 4-го рівня не буде використовуватися / дозволятись.

Але вкладений приватний клас є допустимим, оскільки прямий зовнішній - це клас, а не пакет, наприклад :

class PrivateNestedMain {
    private static class Inner {
        public static void main(String[] args) {
            System.out.println("Hello from Inner!");
        }
    }
}

А що, якщо дозволить "захищений клас foo"? захищеною головною характеристикою є підклас, тому зовнішній (пакет) ПОВИНЕН (через суттєвий обсяг, але все ще необов’язковий) надає стиль підкласу , тобто підпакет, або package A extends package B, але ми не знаємо такого. Отже, захищений не може використовувати повний потенціал (основна сфера дії - для підкласу) у верхньому рівні, який є зовнішнім пакетом (тобто немає такого підпакета), але захищений може використовувати повний потенціал у вкладеному класі, зовнішнім є клас ( тобто може бути підкласом) :

class ProtectedNestedMain {
    protected static class Inner {
        public static void main(String[] args) {
            System.out.println("Hello from Inner!");
        }
    }
}

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

Моє заплутування в основному спричинене відомою таблицею за адресою https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html :

введіть тут опис зображення

Якщо дозволено 1-й рівень (загальнодоступний) та 3-й рівень (приватно-пакувальний), як на землі не дозволяється посередній рівень (захищений)?

підклас державної підтримки, який так легко ввести в оману. Правильно читати цю таблицю

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

Те саме введення в оману застосовується до package-private, package-private не підтримує підклас ( N у комірці) не означає, що концепція підкласу застосовується у зовнішньому.

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

введіть тут опис зображення

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

На верхньому рівні - загальнодоступний або приватно-пакувальний (без явного модифікатора).


3

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

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

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

Для отримання додаткової інформації прочитайте, чому зовнішній клас Java не може бути приватним або захищеним


3
Будь ласка, розкрийте будь-які приналежності та не використовуйте веб-сайт як спосіб просування вашого сайту шляхом розміщення публікацій. Дивіться Як написати хорошу відповідь? .

1

Захищений не схожий на загальнодоступний. Захищений має доступ як на рівні пакета, так і за межами пакетів можна отримати доступ лише за успадкуванням .. Якщо клас каже А поза пакетом НАСЛІДУЄ клас з іншого пакета (із захищеним методом за допомогою НАСЛІДОВАННЯ), він може отримати доступ до методів цього класу В, який має захищені методи, але підкласи, похідні від цього класу, тобто, A не можуть отримати доступ до захищених методів .. з public відбувається навпаки ..

Приклад:

package 2;
class B
{
protected void method1()
{
}
}
package 1;
import 2.B;
class A extends B
{
//can access protected method
}
class C extends A
{
//can't access the protected method
}

0

поведінка “protected” = поведінка “за замовчуванням” + “використовувати його в будь-якому підкласі в будь-якому пакунку”.

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


0

Захищений : ВИДИМИЙ лише до рівня упаковки *.

клас визначено захищеним ---> його не можна розширити із зовнішнього пакета (не видно).

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

Те саме стосується визначених приватних класів.

Примітка: Вкладені або внутрішні класи можна визначити захищеними або приватними .

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


0

Відповідь від @ Akash5288 для мене не мала сенсу:

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

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

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

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


0

Що має сенс у цьому питанні, так це те, що JVM написано на C (Sun JVM) та C ++ (oracle JVM), тому під час компіляції ми збираємося створювати файли .class з нашого файлу java, і якщо ми оголосимо клас із захищеним ключовим словом тоді JVM не матиме до нього доступу.

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

Так само клас вищого рівня не може бути приватним. Пояснення нижче:

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

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


0

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

Приклад:

package a;
class parent{
 protected void p();
}
package b;
import a.p;
class child extends parent{
  //you can access method which is protected in the parent in the child 
}
class another extends child {
 //here you can not access the protected method 
}

0

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

Отже, захищений зовнішній клас однаковий із зовнішнім класом (за замовчуванням)!

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