Почему мы не можем определить класс как protected
?
Я знаю, что не можем, но почему? Должна быть какая-то конкретная причина.
Почему мы не можем определить класс как protected
?
Я знаю, что не можем, но почему? Должна быть какая-то конкретная причина.
Ответы:
Потому что в этом нет смысла.
Защищенный член класса (метод или переменная) аналогичен package-private (видимость по умолчанию), за исключением того, что к нему также можно получить доступ из подклассов.
Поскольку в Java нет таких понятий, как «подпакет» или «наследование пакета», объявление класса защищенным или закрытым для пакета было бы тем же самым.
Однако вы можете объявить вложенные и внутренние классы защищенными или частными.
open
в Kotlin, который разрешает создание подклассов вне текущего пакета (можно представить, что protected
в Java это предотвращается с противоположным значением по умолчанию).
Как вы знаете, по умолчанию используется доступ на уровне пакета, а защищенный - для уровня пакета плюс классы, не входящие в пакет, но расширяет этот класс (здесь следует отметить, что вы можете расширять класс, только если он виден!). Скажем так:
Поскольку нет способа ограничить наследование этого класса только несколькими классами (мы не можем ограничить класс, наследуемый только несколькими классами из всех доступных классов в пакете / вне пакета), спецификаторы защищенного доступа не используются. для классов высшего уровня. Следовательно, это запрещено.
public class A
{
protected class B
{
}
}
Ответ @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 модификатора доступа:
На верхнем уровне - общедоступный или частный для пакета (без явного модификатора).
Определение защищенного поля делает это поле доступным внутри пакета, а также за его пределами только посредством наследования (только внутри дочернего класса).
Итак, если нам разрешено сделать класс защищенным, мы можем очень легко получить к нему доступ внутри пакета, но для доступа к этому классу вне пакета нам сначала нужно расширить ту сущность, в которой определен этот класс, который является его пакетом.
А поскольку пакет не может быть расширен (может быть импортирован), определение защищенного класса снова сделает его закрытым для пакета, что похоже на определение его по умолчанию, которое мы уже можем сделать. Следовательно, определение частного класса бесполезно, это только сделает ситуацию неоднозначной.
Для получения дополнительной информации прочтите, почему внешний класс Java не может быть частным или защищенным.
Защищено не похоже на публичное. 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
}
поведение «protected» = поведение «по умолчанию» + «использовать его в любом подклассе в любом пакете».
В любом случае у нас есть модификатор доступа по умолчанию для класса, единственное преимущество, которое мы можем получить от модификатора защищенного доступа, это: - используя его в любом пакете посредством создания подклассов. Но для подкласса видимость родительского «защищенного» класса была бы частной. Так что к нему нельзя получить доступ. В основном, если у вас есть защищенный класс верхнего уровня, никакой внешний класс не может получить доступ, создав его подкласс. Так защищать для класса верхнего уровня бессмысленно.
Защищено : ВИДИМО только на уровне пакета *.
класс определен как защищенный ---> он не может быть расширен извне пакета (не виден).
И если он не может быть расширен, то бессмысленно сохранять его защищенным , потому что тогда он станет доступным по умолчанию, который разрешен.
То же самое относится к частным определенным классам.
Примечание. Вложенные или внутренние классы могут быть определены как защищенные или частные .
* : Изучите защищенное ключевое слово, для этого ответа я сделал его кратким.
Ответ от @ Akash5288 не имел для меня никакого смысла:
Если всем классам разрешено создавать подклассы, это будет похоже на спецификатор открытого доступа.
Поскольку нет способа ограничить наследование этого класса только несколькими классами (мы не можем ограничить класс, наследуемый только несколькими классами из всех доступных классов в пакете / вне пакета), спецификаторы защищенного доступа не используются. для классов высшего уровня. Следовательно, это запрещено.
Затем вы можете применить ту же логику к защищенным методам и переменным, они также «похожи на общедоступные». Все классы вне пакета могут расширять наш общедоступный класс и использовать его защищенные методы. Почему можно ограничивать методы и переменные расширенными классами, но нельзя ограничивать весь класс? «Подобный публике» не означает «то же самое, что и публика». Моя интерпретация такова, что вполне нормально разрешить защищенный класс, как и разрешить защищенные методы.
Ответ «вы не можете расширить класс, к которому вы не можете получить доступ / не видите» более логичен.
Что имеет смысл в этом вопросе, так это то, что JVM написана на C (Sun JVM) и C ++ (Oracle JVM), поэтому во время компиляции мы будем создавать файлы .class из нашего файла java, и если мы объявим класс с ключевым словом Protected тогда он не будет доступен для JVM.
Ответ, почему защищенный класс не будет доступен для JVM, заключается в том, что, поскольку защищенные поля доступны в одном пакете или в другом пакете только через наследование, а JVM не написана таким образом, чтобы она унаследовала класс от класса. Надеюсь, это удовлетворит этот вопрос :)
Точно так же класс верхнего уровня не может быть частным. Объяснение, как показано ниже:
Итак, что произойдет, если мы определим частный класс, этот класс будет доступен только внутри сущности, в которой он определен, а в нашем случае это его пакет?
Таким образом, определение частного доступа к классу сделает его доступным внутри того же пакета, что и ключевое слово по умолчанию для нас. Следовательно, определение частного класса бесполезно, оно только сделает вещи неоднозначными.
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
}
если внешний класс объявлен protected, я думаю, вы хотите, чтобы к классу можно было получить доступ только из того же пакета и его подкласса, но из разных пакетов. Однако невозможно создать подклассы для защищенного класса, потому что, когда вы пишете «class Dog extends Animal», из-за того, что защищенный «Animal» может быть доступен только его подклассу, очевидно, «Dog» не является подклассом «Animal» .
Таким образом, защищенный внешний класс совпадает с (по умолчанию) внешним классом!