Digamos simplemente por qué la clase externa no puede protegerse. Las clases internas se pueden proteger.
Number945
Respuestas:
101
Porque no tiene sentido.
El miembro de clase protegido (método o variable) es como paquete privado (visibilidad predeterminada), excepto que también se puede acceder a él desde subclases.
Dado que no existe un concepto como 'subpaquete' o 'herencia de paquete' en Java, declarar la clase protegida o el paquete privado sería lo mismo.
Sin embargo, puede declarar clases anidadas e internas como protegidas o privadas.
> Dado que no existe un concepto como 'subpaquete' o 'herencia de paquete' en Java, declarar la clase protegida o el paquete privado sería lo mismo. ¿Por qué la clase protegida tendría la misma visibilidad que el paquete privado? ¿No es lo mismo que público? Gracias.
yaromir
@Nikita Ryback ¿Puedes explicar qué es subpaquete o herencia de paquete? Todavía no tengo claro por qué se usa protected en la clase de nivel superior. Si lo explicas con un ejemplo, será genial.
App Kart
Cuando declaras un miembro de clase como protegido, su visibilidad son las clases en el mismo paquete (llamado acceso al paquete) y la subclase . Si intenta acceder desde una clase externa en otro paquete, este miembro de método protegido no es visible.
kelgwiin
@kelgwiin Creo que no deberías mezclar modificadores de acceso de clases y miembros. Porque los dos son diferentes. Si bien las clases se pueden modificar como públicas o predeterminadas, los miembros podrían modificarse como públicos, privados, protegidos y predeterminados.
Sharhp
2
"Porque no tiene sentido", es una declaración bastante atrevida. No está definido en Java, pero las cosas similares no existe; por ejemplo, openen Kotlin que permite subclases fuera del paquete actual (uno podría imaginar protecteden Java evitando eso, con el valor predeterminado opuesto).
Raphael
41
Como sabe, el valor predeterminado es para el acceso a nivel de paquete y protegido es para el nivel de paquete más las clases que no son de paquete, pero lo que amplía esta clase (¡Debe tenerse en cuenta aquí es que puede ampliar la clase solo si está visible!). Digámoslo de esta manera:
La clase protegida de nivel superior sería visible para las clases de su paquete.
ahora hacerlo visible fuera del paquete (subclases) es un poco confuso y complicado. ¿Qué clases deberían poder heredar nuestra clase protegida?
Si a todas las clases se les permite subclase, será similar al especificador de acceso público.
Si no hay ninguno, es similar al predeterminado.
Dado que no hay forma de restringir que esta clase sea subclasificada por solo unas pocas clases (no podemos restringir que la clase sea heredada por solo unas pocas clases de todas las clases disponibles en un paquete / fuera de un paquete), no hay uso de especificadores de acceso protegido para clases de alto nivel. Por tanto, no está permitido.
"Ahora hacer que una clase protegida sea visible fuera del paquete (subclases) es un poco confuso y complicado. ¿A qué clases se les debe permitir heredar nuestra clase protegida? y si todas las clases pueden subclasificar, entonces será similar al especificador de acceso público". realmente me ayudó a entender el problema de por qué las clases protegidas no tienen sentido :)
La respuesta de @Nikita Rybak tiene buenos puntos pero falta de detalles, no puedo simplemente entender la idea sin pensar profundamente, lo siguiente es lo que pensé y ahora debería entender completamente la razón.
Cuatro modificadores de acceso, suponiendo que el primer nivel es público y el cuarto nivel es privado (según esta tabla en secuencia). Lo primero que debemos saber es por qué la clase no se puede definir como privada en el nivel superior.
Entonces, si la "clase privada foo" (un miembro privado definido, es decir, la clase misma es un miembro) lo permite, ¿cuál es el exterior (que contiene el miembro)? Alcance del archivo? No, el archivo externo no tiene sentido porque incluso varias clases en un solo archivo se compilarán en archivos de clase separados. Entonces el exterior es el paquete . Pero el modificador de acceso predeterminado de tercer nivel ya significa "paquete privado ". Por lo tanto, el modificador de acceso privado de 4 ° nivel no se utilizará / permitirá.
Pero la clase privada anidada está permitida porque el exterior directo es clase, no paquete, por ejemplo :
classPrivateNestedMain{
privatestaticclassInner{
publicstaticvoidmain(String[] args){
System.out.println("Hello from Inner!");
}
}
}
Ahora, ¿qué pasa si la "clase protegida foo" lo permite? La característica principal protegida es la subclase, por lo que el (paquete) externo DEBERÍA (debido al alcance, pero aún es opcional) proporcionar el estilo de la subclase , es decir, el subpaquete, o package A extends package B, pero no sabemos tal cosa. Por lo tanto, protected no puede usar todo el potencial (el alcance principal es para toda la subclase) en el nivel superior en el que el exterior es el paquete (es decir, no hay tal subpaquete), pero protected puede utilizar todo el potencial en la clase anidada, que el exterior es la clase ( es decir, puede ser una subclase) :
classProtectedNestedMain{
protectedstaticclassInner{
publicstaticvoidmain(String[] args){
System.out.println("Hello from Inner!");
}
}
}
Tenga en cuenta que lo anterior dijo "no se puede utilizar todo el potencial" debido a que no puede llegar a toda la subclase simplemente porque no hay una subclase externa, eso significa que se puede permitir realmente protegido , es solo una cuestión de elección para evitar duplicar el trabajo del paquete -privado si externo no apto para subclase , ver más abajo.
Si el 1er nivel (público) y el 3er nivel (paquete privado) están permitidos, ¿cómo diablos no se permite el 2º nivel intermedio (protegido)?
subclase de apoyo público tan fácil de engañar. La forma correcta de leer esta tabla es
subclase de soporte público si el exterior tiene una característica de subclase.
El mismo engaño se aplica a package-private, package-private no admite subclase ( N en celda) no significa que el concepto de subclase se aplique en el exterior.
Eso significa que debemos ignorar la columna Subclase si la función de subclase no está disponible en el exterior:
Como podemos ver ahora, tanto protected como package-private tienen el mismo nivel ahora ( YYN ), no más confusión sobre por qué no se permite el nivel intermedio. En general, Java elige solo paquete-privado sobre protegido para evitar confusiones ( es solo una cuestión de elección , pero la característica principal protegida es la subclase, por lo que el paquete-privado es superior) y, como resultado , solo se permiten 2 modificadores de acceso en el nivel superior:
En el nivel superior: público o paquete-privado (sin modificador explícito).
La definición de un campo protegido hace que ese campo sea accesible dentro del paquete, así como fuera del paquete solo a través de herencia (solo dentro de la clase secundaria).
Entonces, si se nos permite hacer una clase protegida, podemos acceder a ella dentro del paquete muy fácilmente, pero para acceder a esa clase fuera del paquete, primero debemos extender esa entidad en la que se define esta clase, que es su paquete.
Y dado que un paquete no se puede extender (se puede importar), definir una clase protegida volverá a hacer que el paquete sea privado, lo cual es similar a definirlo como predeterminado, lo que ya podemos hacer. Por lo tanto, definir una clase privada no tiene ningún beneficio, solo hará que las cosas sean ambiguas.
Protegido no es similar al público. Protected tiene acceso a nivel de paquete y se puede acceder fuera de los paquetes solo por herencia. Si una clase dice A fuera de un paquete HEREDA una clase de otro paquete (con el método protegido usando HERENCIA), puede acceder a los métodos de esta clase B que tiene métodos protegidos pero las subclases derivadas de esta clase, es decir, A no puede acceder a los métodos protegidos ... sucede lo contrario con el público ...
comportamiento de "protegido" = comportamiento de "predeterminado" + "usarlo en cualquier subclase en cualquier paquete".
De todos modos, tenemos un modificador de acceso predeterminado para la clase, la única ventaja que podemos obtener del modificador de acceso protegido es: - usándolo en cualquier paquete mediante subclases. Pero para la subclase, la visibilidad de la clase principal "protegida" sería privada. Entonces no se puede acceder. Básicamente, si tiene una clase de nivel superior protegida, ninguna clase externa puede obtener acceso subclasificando. Tan protegido para una clase de alto nivel no tiene sentido.
La respuesta de @ Akash5288 no tenía sentido para mí:
Si a todas las clases se les permite subclase, será similar al especificador de acceso público.
Dado que no hay forma de restringir que esta clase sea subclasificada por solo unas pocas clases (no podemos restringir que la clase sea heredada por solo unas pocas clases de todas las clases disponibles en un paquete / fuera de un paquete), no hay uso de especificadores de acceso protegido para clases de alto nivel. Por tanto, no está permitido.
A continuación, puede aplicar la misma lógica a los métodos y variables protegidos, que también son "similares a públicos". Todas las clases fuera de un paquete pueden extender nuestra clase pública y usar sus métodos protegidos. ¿Por qué está bien restringir métodos y variables a clases extendidas, pero restringir toda la clase no? "Similar al público" no es "similar al público". Mi interpretación es que está perfectamente bien permitir una clase protegida, ya que está bien permitir métodos protegidos.
La respuesta "no se puede extender una clase a la que no se puede acceder / ver" es más lógica.
Lo que tiene sentido para esta pregunta es que, JVM está escrito en C (Sun JVM) y C ++ (oracle JVM), por lo que durante la compilación, crearemos archivos .class a partir de nuestro archivo java y si declaramos una clase con la palabra clave protegida entonces JVM no accederá a él.
La respuesta por la que JVM no accederá a la clase protegida es que, dado que los campos protegidos son accesibles dentro del mismo paquete o para un paquete diferente solo a través de la herencia y la JVM no está escrita de una manera que herede la clase will. Espero que esto satisfaga esta pregunta :)
Del mismo modo, una clase de nivel superior no puede ser privada. Explicación de la siguiente manera:
Entonces, ¿qué pasará si definimos una clase privada, esa clase solo será accesible dentro de la entidad en la que está definida que en nuestro caso es su paquete?
Por lo tanto, definir el acceso privado a la clase lo hará accesible dentro del mismo paquete que la palabra clave predeterminada ya lo hace para nosotros. Por lo tanto, definir una clase privada no tiene ningún beneficio, solo hará que las cosas sean ambiguas.
protegido significa que cualquier clase del mismo paquete y subclases pueden acceder al miembro incluso si están en otros paquetes.
Ejemplo:
package a;
classparent{
protectedvoidp();
}
package b;
import a.p;
classchildextendsparent{
//you can access method which is protected in the parent in the child
}
classanotherextendschild{
//here you can not access the protected method
}
Si una clase externa es declarada por protected, creo que desea que solo se pueda acceder a la clase desde el mismo paquete y su subclase pero con paquetes diferentes. Sin embargo, no es posible crear subclases para una clase protegida, porque cuando escribes "clase Perro extiende Animal", debido a que el "Animal" protegido solo puede ser accedido por su subclase, obviamente, "Perro" no es la subclase "Animal" .
¡Así que la clase externa protegida es la misma que la clase externa (predeterminada)!
Respuestas:
Porque no tiene sentido.
El miembro de clase protegido (método o variable) es como paquete privado (visibilidad predeterminada), excepto que también se puede acceder a él desde subclases.
Dado que no existe un concepto como 'subpaquete' o 'herencia de paquete' en Java, declarar la clase protegida o el paquete privado sería lo mismo.
Sin embargo, puede declarar clases anidadas e internas como protegidas o privadas.
fuente
open
en Kotlin que permite subclases fuera del paquete actual (uno podría imaginarprotected
en Java evitando eso, con el valor predeterminado opuesto).Como sabe, el valor predeterminado es para el acceso a nivel de paquete y protegido es para el nivel de paquete más las clases que no son de paquete, pero lo que amplía esta clase (¡Debe tenerse en cuenta aquí es que puede ampliar la clase solo si está visible!). Digámoslo de esta manera:
Dado que no hay forma de restringir que esta clase sea subclasificada por solo unas pocas clases (no podemos restringir que la clase sea heredada por solo unas pocas clases de todas las clases disponibles en un paquete / fuera de un paquete), no hay uso de especificadores de acceso protegido para clases de alto nivel. Por tanto, no está permitido.
fuente
public class A { protected class B { } }
fuente
La respuesta de @Nikita Rybak tiene buenos puntos pero falta de detalles, no puedo simplemente entender la idea sin pensar profundamente, lo siguiente es lo que pensé y ahora debería entender completamente la razón.
Cuatro modificadores de acceso, suponiendo que el primer nivel es público y el cuarto nivel es privado (según esta tabla en secuencia). Lo primero que debemos saber es por qué la clase no se puede definir como privada en el nivel superior.
Entonces, si la "clase privada foo" (un miembro privado definido, es decir, la clase misma es un miembro) lo permite, ¿cuál es el exterior (que contiene el miembro)? Alcance del archivo? No, el archivo externo no tiene sentido porque incluso varias clases en un solo archivo se compilarán en archivos de clase separados. Entonces el exterior es el paquete . Pero el modificador de acceso predeterminado de tercer nivel ya significa "paquete privado ". Por lo tanto, el modificador de acceso privado de 4 ° nivel no se utilizará / permitirá.
Pero la clase privada anidada está permitida porque el exterior directo es clase, no paquete, por ejemplo :
class PrivateNestedMain { private static class Inner { public static void main(String[] args) { System.out.println("Hello from Inner!"); } } }
Ahora, ¿qué pasa si la "clase protegida foo" lo permite? La característica principal protegida es la subclase, por lo que el (paquete) externo DEBERÍA (debido al alcance, pero aún es opcional) proporcionar el estilo de la subclase , es decir, el subpaquete, o
package A extends package B
, pero no sabemos tal cosa. Por lo tanto, protected no puede usar todo el potencial (el alcance principal es para toda la subclase) en el nivel superior en el que el exterior es el paquete (es decir, no hay tal subpaquete), pero protected puede utilizar todo el potencial en la clase anidada, que el exterior es la clase ( es decir, puede ser una subclase) :class ProtectedNestedMain { protected static class Inner { public static void main(String[] args) { System.out.println("Hello from Inner!"); } } }
Tenga en cuenta que lo anterior dijo "no se puede utilizar todo el potencial" debido a que no puede llegar a toda la subclase simplemente porque no hay una subclase externa, eso significa que se puede permitir realmente protegido , es solo una cuestión de elección para evitar duplicar el trabajo del paquete -privado si externo no apto para subclase , ver más abajo.
Mi confusión se debe principalmente a la famosa tabla en https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html :
Si el 1er nivel (público) y el 3er nivel (paquete privado) están permitidos, ¿cómo diablos no se permite el 2º nivel intermedio (protegido)?
subclase de apoyo público tan fácil de engañar. La forma correcta de leer esta tabla es
El mismo engaño se aplica a package-private, package-private no admite subclase ( N en celda) no significa que el concepto de subclase se aplique en el exterior.
Eso significa que debemos ignorar la columna Subclase si la función de subclase no está disponible en el exterior:
Como podemos ver ahora, tanto protected como package-private tienen el mismo nivel ahora ( YYN ), no más confusión sobre por qué no se permite el nivel intermedio. En general, Java elige solo paquete-privado sobre protegido para evitar confusiones ( es solo una cuestión de elección , pero la característica principal protegida es la subclase, por lo que el paquete-privado es superior) y, como resultado , solo se permiten 2 modificadores de acceso en el nivel superior:
fuente
La definición de un campo protegido hace que ese campo sea accesible dentro del paquete, así como fuera del paquete solo a través de herencia (solo dentro de la clase secundaria).
Entonces, si se nos permite hacer una clase protegida, podemos acceder a ella dentro del paquete muy fácilmente, pero para acceder a esa clase fuera del paquete, primero debemos extender esa entidad en la que se define esta clase, que es su paquete.
Y dado que un paquete no se puede extender (se puede importar), definir una clase protegida volverá a hacer que el paquete sea privado, lo cual es similar a definirlo como predeterminado, lo que ya podemos hacer. Por lo tanto, definir una clase privada no tiene ningún beneficio, solo hará que las cosas sean ambiguas.
Para obtener más información, lea Por qué una clase Java externa no puede ser privada o protegida
fuente
Protegido no es similar al público. Protected tiene acceso a nivel de paquete y se puede acceder fuera de los paquetes solo por herencia. Si una clase dice A fuera de un paquete HEREDA una clase de otro paquete (con el método protegido usando HERENCIA), puede acceder a los métodos de esta clase B que tiene métodos protegidos pero las subclases derivadas de esta clase, es decir, A no puede acceder a los métodos protegidos ... sucede lo contrario con el público ...
Ejemplo:
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 }
fuente
comportamiento de "protegido" = comportamiento de "predeterminado" + "usarlo en cualquier subclase en cualquier paquete".
De todos modos, tenemos un modificador de acceso predeterminado para la clase, la única ventaja que podemos obtener del modificador de acceso protegido es: - usándolo en cualquier paquete mediante subclases. Pero para la subclase, la visibilidad de la clase principal "protegida" sería privada. Entonces no se puede acceder. Básicamente, si tiene una clase de nivel superior protegida, ninguna clase externa puede obtener acceso subclasificando. Tan protegido para una clase de alto nivel no tiene sentido.
fuente
Protegido : VISIBLE solo a nivel de paquete *.
la clase está definida protegida ---> no se puede extender desde un paquete externo (no visible).
Y si no se puede extender, no tiene sentido mantenerlo protegido , porque entonces se convertirá en el acceso predeterminado que está permitido.
Lo mismo se aplica a las clases privadas definidas.
Nota: Las clases anidadas o internas se pueden definir protegidas o privadas .
* : Explore la palabra clave protegida , para esta respuesta la hice concisa.
fuente
La respuesta de @ Akash5288 no tenía sentido para mí:
A continuación, puede aplicar la misma lógica a los métodos y variables protegidos, que también son "similares a públicos". Todas las clases fuera de un paquete pueden extender nuestra clase pública y usar sus métodos protegidos. ¿Por qué está bien restringir métodos y variables a clases extendidas, pero restringir toda la clase no? "Similar al público" no es "similar al público". Mi interpretación es que está perfectamente bien permitir una clase protegida, ya que está bien permitir métodos protegidos.
La respuesta "no se puede extender una clase a la que no se puede acceder / ver" es más lógica.
fuente
Lo que tiene sentido para esta pregunta es que, JVM está escrito en C (Sun JVM) y C ++ (oracle JVM), por lo que durante la compilación, crearemos archivos .class a partir de nuestro archivo java y si declaramos una clase con la palabra clave protegida entonces JVM no accederá a él.
La respuesta por la que JVM no accederá a la clase protegida es que, dado que los campos protegidos son accesibles dentro del mismo paquete o para un paquete diferente solo a través de la herencia y la JVM no está escrita de una manera que herede la clase will. Espero que esto satisfaga esta pregunta :)
Del mismo modo, una clase de nivel superior no puede ser privada. Explicación de la siguiente manera:
Entonces, ¿qué pasará si definimos una clase privada, esa clase solo será accesible dentro de la entidad en la que está definida que en nuestro caso es su paquete?
Por lo tanto, definir el acceso privado a la clase lo hará accesible dentro del mismo paquete que la palabra clave predeterminada ya lo hace para nosotros. Por lo tanto, definir una clase privada no tiene ningún beneficio, solo hará que las cosas sean ambiguas.
fuente
protegido significa que cualquier clase del mismo paquete y subclases pueden acceder al miembro incluso si están en otros paquetes.
Ejemplo:
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 }
fuente
Si una clase externa es declarada por protected, creo que desea que solo se pueda acceder a la clase desde el mismo paquete y su subclase pero con paquetes diferentes. Sin embargo, no es posible crear subclases para una clase protegida, porque cuando escribes "clase Perro extiende Animal", debido a que el "Animal" protegido solo puede ser accedido por su subclase, obviamente, "Perro" no es la subclase "Animal" .
¡Así que la clase externa protegida es la misma que la clase externa (predeterminada)!
fuente