java - polimorfismo - modificadores de acceso poo
En Java, ¿por qué se puede acceder a un miembro protegido desde fuera de la clase dentro del mismo paquete? (5)
Esta pregunta ya tiene una respuesta aquí:
En su libro, Herbert Schildt dice en la página 172 (tercer párrafo) que " protegido se aplica solo cuando se trata de una herencia".
En la página 228, la Tabla 9-1 muestra que se puede acceder a un miembro protegido desde una no-clase dentro del mismo paquete.
El siguiente código funciona y respalda la información en la Tabla 9-1.
Class1.java:
package Mypack;
public class Class1
{
protected pro=1;
public Class1()
{
System.out.println(pro);
}
}
Class2.java
package Mypack;
class Class2 extends Class1
{
Class2()
{
System.out.println(pro);
}
}
Class3.java
package Mypack;
class Class3
{
Class3()
{
Class1 class1=new Class1();
System.out.println(class1.pro);
}
}
Está bien que se pueda acceder a la variable pro desde la clase derivada Class2 . Pero, ¿cómo puede accederse a ella desde la clase no derivada Class3 a través de una referencia a un objeto de Class1? Contradice la afirmación en la página 172. Si es así, entonces no encuentro ninguna diferencia entre el público y los especificadores protegidos en esta situación.
El modificador protegido especifica que solo se puede acceder al miembro dentro de su propio paquete (como con el paquete privado) y, además, mediante una subclase de su clase en otro paquete. https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
En su libro, Herbert Schildt dice en la página 172 (tercer párrafo) que "protegido se aplica solo cuando se trata de una herencia".
Hay un argumento de que esa afirmación es correcta, aunque diría que es bastante engañosa. Veamos el gráfico de acceso del tutorial de control de acceso :
Modifier Class Package Subclass World public Y Y Y Y protected Y Y Y N no modifier Y Y N N private Y N N N
Tenga en cuenta que ningún modificador otorga acceso de clase y paquete al miembro, y no otorga acceso a subclases o al mundo. protected
solo cambia una de esas cosas: hace que el miembro esté disponible para las subclases. Entonces, en ese sentido, tiene razón: solo se aplica cuando se trata de una herencia; sin herencia, es lo mismo que no tener modificador.
Pero me parece bastante engañoso, por la razón que inspiró su pregunta: parece implicar que no habrá acceso a los paquetes. La única forma en que la declaración tiene sentido es si ya sabe que ningún modificador otorga acceso al paquete.
Para mayor claridad: protected
significa que un miembro está disponible para cualquier clase en el paquete y para codificar en subclases. Al hacer esto, es posible que una biblioteca tenga campos y métodos a los que solo accede desde el código que forma parte de la biblioteca * (más o menos, vea a continuación) o un código que ayude a implementar algo en la biblioteca (por ejemplo, si realiza subclases de una de las clases de biblioteca). No hay un "por qué" en particular, aparte de cómo se diseñó el lenguaje.
Si es así, entonces no encuentro ninguna diferencia entre el público y los especificadores protegidos en esta situación.
En esta situación , no. Sin embargo, obviamente hay una gran diferencia cuando se considera un código que no está en el mismo paquete y no está en una clase derivada de un miembro del paquete: ese código no tiene acceso a protected
miembros protected
.
Esto está cubierto en JLS§6.6.1 :
... si el miembro o el constructor se declara
protected
, entonces el acceso solo se permite cuando se cumple una de las siguientes condiciones:
El acceso al miembro o al constructor ocurre dentro del paquete que contiene la clase en la que se declara el miembro o constructor protegido.
El acceso es correcto como se describe en §6.6.2.
(note la primera viñeta) y JLS§6.6.2 :
Se puede acceder a un miembro o constructor
protected
de un objeto desde fuera del paquete en el que se declara solo por el código que es responsable de la implementación de ese objeto.
("código que es responsable de la implementación de ese objeto", por ejemplo, código en una subclase.)
* Re my "en cierto modo, ver más abajo" en "Hacer esto hace posible que una biblioteca tenga campos y métodos a los que solo accede desde el código que forma parte de la biblioteca ..." Eso no es realmente cierto, porque excepto por los paquetes restringidos ( java.lang
, por ejemplo), puede escribir su propia clase diciendo que está en el paquete de la biblioteca, y luego usar los campos y métodos a nivel de paquete de las clases de la biblioteca. El concepto de paquete de Java no es un mecanismo de seguridad de campo / método.
Si es así, entonces no encuentro ninguna diferencia entre el público y los especificadores protegidos en esta situación
Eso es correcto, no hay diferencia en esa situación.
Considere este código:
package otherpack;
public class Class4
{
Class4()
{
Class1 class1=new Class1(); // Ok, Class1 and it''s constructor are public
System.out.println(class1.pro); // Compilation error. pro is protected
}
}
package otherpack;
public class Class5 extends Class1
{
Class5()
{
Class1 class1=new Class1(); // Ok, Class1 and it''s constructor are public
System.out.println(class1.pro); // OK, Class5 extends Class1 and pro is protected
}
}
En la situación del código en un paquete diferente, el público y el protegido son diferentes. Puede usar miembros públicos de diferentes paquetes pero no miembros protegidos a menos que lo haga en una clase derivada.
Algo que se declara protected
es visible para sí mismo, sus hijos y el paquete en el que se declara.
Si Class3
estuviera en un paquete diferente, como mypack.nested
, entonces no podría acceder a class1.pro
en absoluto.
La tabla en este enlace muestra los modificadores frente a lo que se puede acceder a http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html . Luego se elige el modificador en función de factores como lo que debe ocultarse a otra clase, lo que debe compartirse de acuerdo con buenos principios como encapsulación, etc.
Niveles de acceso
Modificador Clase Paquete Subclase Mundo
público YYYY
YYYN protegido
sin modificador YYNN
YNNN privada