Почему класс нельзя определить как защищенный?


89

Почему мы не можем определить класс как protected?

Я знаю, что не можем, но почему? Должна быть какая-то конкретная причина.


3
Что бы он сделал, если бы вы объявили класс защищенным?

1
Я думаю, что это то, что вы ищете: stackoverflow.com/questions/2534733/java-protected-classes : D
dewijones92

2
Скажем так, почему внешний класс нельзя защитить? Внутренние классы можно защитить.
Number945 06

Ответы:


101

Потому что в этом нет смысла.

Защищенный член класса (метод или переменная) аналогичен package-private (видимость по умолчанию), за исключением того, что к нему также можно получить доступ из подклассов.
Поскольку в Java нет таких понятий, как «подпакет» или «наследование пакета», объявление класса защищенным или закрытым для пакета было бы тем же самым.

Однако вы можете объявить вложенные и внутренние классы защищенными или частными.


> Поскольку в Java нет таких понятий, как «подпакет» или «наследование пакета», объявление класса защищенным или закрытым для пакета было бы тем же самым. Почему защищенный класс будет иметь такую ​​же видимость, как и частный пакет? Разве это не то же самое, что и публичное? Спасибо.
Яромир 01

@Nikita Ryback: Можете ли вы объяснить, что такое subPackage или наследование пакетов? Я до сих пор не понимаю, почему protected используется в классе верхнего уровня. Если вы объясните пример, это будет здорово.
App Kart

Когда вы объявляете член класса защищенным, его видимость - это классы в одном пакете (так называемый доступ к пакету) и подклассы . Если вы попытаетесь получить доступ из внешнего класса в другом пакете, этот член защищенного метода не будет виден.
kelgwiin

@kelgwiin Я считаю, что не следует смешивать модификаторы доступа классов и членов. Потому что они разные. Хотя классы позволяют изменять себя как общедоступные или по умолчанию, члены могут быть изменены как общедоступные, частные, защищенные и по умолчанию.
Sharhp 09

2
«Потому что в этом нет смысла» - довольно смелое заявление. Это не определено в Java, но подобные вещи действительно существуют; например, openв Kotlin, который разрешает создание подклассов вне текущего пакета (можно представить, что protectedв Java это предотвращается с противоположным значением по умолчанию).
Рафаэль

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!");
        }
    }
}

А что, если разрешить "protected class foo"? Основная характеристика protected - подкласс, поэтому внешний (пакет) ДОЛЖЕН (из-за расширенной области видимости, но все же он необязателен) предоставлять стиль подкласса , то есть подпакета, или package A extends package B, но мы этого не знаем. Таким образом, защищенный не может использовать весь потенциал (основная область - это подкласс) на верхнем уровне, внешний вид которого является пакетом (т.е. нет такой вещи подпакета), но защищенный может использовать весь потенциал во вложенном классе, внешний - это класс ( т.е. может быть подклассом) :

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

Обратите внимание, что вышеупомянутый «не может использовать весь потенциал» из-за того, что он не может достичь всего подкласса просто потому, что нет внешнего подкласса, это означает, что фактически защищенный может быть разрешен , это просто вопрос выбора, чтобы избежать дублирования работы пакета -private, если внешний не подклассифицируется , см. ниже.

Мое замешательство в основном вызвано известной таблицей на https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html :

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

Если 1-й уровень (общедоступный) и 3-й уровень (частный пакет) разрешены, как вообще не разрешен промежуточный 2-й уровень (защищенный)?

подкласс общественной поддержки, который легко ввести в заблуждение. Правильный способ чтения этой таблицы:

подкласс публичной поддержки, если внешний имеет функцию подкласса.

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

Это означает , что мы должны игнорировать Подкласс столбец , если функция подкласса не доступна в наружном:

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

Как мы теперь видим, и protected, и package-private теперь имеют один и тот же уровень ( YYN ), больше нет путаницы в том, почему промежуточный уровень не разрешен. В целом, Java выбирает только частный пакет вместо защищенного, чтобы избежать путаницы ( это просто вопрос выбора , но защищенная основная характеристика - подкласс, поэтому частный пакет лучше), и в результате на верхнем уровне разрешены только 2 модификатора доступа:

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


3

Определение защищенного поля делает это поле доступным внутри пакета, а также за его пределами только посредством наследования (только внутри дочернего класса).

Итак, если нам разрешено сделать класс защищенным, мы можем очень легко получить к нему доступ внутри пакета, но для доступа к этому классу вне пакета нам сначала нужно расширить ту сущность, в которой определен этот класс, который является его пакетом.

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

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


3
Пожалуйста, сообщайте о любой аффилированности и не используйте сайт как способ продвижения вашего сайта посредством публикации. См. Как мне написать хороший ответ? .

1

Защищено не похоже на публичное. Protected имеет доступ как на уровне пакета, так и за пределами пакетов только посредством наследования. Если класс говорит A вне пакета INHERITS a class from other package (with protected method by using INHERITANCE), он может получить доступ к методам этого класса B, которые имеет защищенные методы, но подклассы, производные от этого класса, т. е. A не может получить доступ к защищенным методам .. противоположное происходит с общедоступными ..

Пример:

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, и если мы объявим класс с ключевым словом Protected тогда он не будет доступен для JVM.

Ответ, почему защищенный класс не будет доступен для JVM, заключается в том, что, поскольку защищенные поля доступны в одном пакете или в другом пакете только через наследование, а JVM не написана таким образом, чтобы она унаследовала класс от класса. Надеюсь, это удовлетворит этот вопрос :)

Точно так же класс верхнего уровня не может быть частным. Объяснение, как показано ниже:

Итак, что произойдет, если мы определим частный класс, этот класс будет доступен только внутри сущности, в которой он определен, а в нашем случае это его пакет?

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


0

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

Пример:

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

если внешний класс объявлен protected, я думаю, вы хотите, чтобы к классу можно было получить доступ только из того же пакета и его подкласса, но из разных пакетов. Однако невозможно создать подклассы для защищенного класса, потому что, когда вы пишете «class Dog extends Animal», из-за того, что защищенный «Animal» может быть доступен только его подклассу, очевидно, «Dog» не является подклассом «Animal» .

Таким образом, защищенный внешний класс совпадает с (по умолчанию) внешним классом!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.