¿Por qué no podemos definir una clase como protected
?
Sé que no podemos, pero ¿por qué? Debería haber alguna razón específica.
¿Por qué no podemos definir una clase como protected
?
Sé que no podemos, pero ¿por qué? Debería haber alguna razón específica.
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.
open
en Kotlin que permite subclases fuera del paquete actual (uno podría imaginar protected
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.
public class A
{
protected class B
{
}
}
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
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.
Para obtener más información, lea Por qué una clase Java externa no puede ser privada o protegida
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
}
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.
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.
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;
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
}
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)!