java - sencillo - ¿Cómo acceder a las variables privadas de una clase en su subclase?
llamar una variable de otra clase c# (28)
Esta es una pregunta que me hicieron en una entrevista: tengo clase A con miembros privados y la clase B se extiende A. Sé que no se puede acceder a los miembros privados de una clase, pero la pregunta es: necesito acceder a miembros privados de la clase A desde clase B, en lugar de crear variables con el mismo valor en la clase B.
¡¡¡Sencillo!!!
public class A{
private String a;
private String b;
//getter and setter are here
}
public class B extends A{
public B(String a, String b){ //constructor
super(a,b)//from here you got access with private variable of class A
}
}
Gracias
¿Has pensado en hacerlos protegidos ? Solo para estar seguro de que estás al tanto de esta opción, si me perdonas por traer esta trivia;)
¿Reflexión? Omitiendo las importaciones, esto debería funcionar:
public class A {
private int ii = 23;
}
public class B extends A {
private void readPrivateSuperClassField() throws Exception {
Class<?> clazz = getClass().getSuperclass();
Field field = clazz.getDeclaredField("ii");
field.setAccessible(true);
System.out.println(field.getInt(this));
}
public static void main(String[] args) throws Exception {
new B().readPrivateSuperClassField();
}
}
No funcionará si haces algo así antes de la invocación readPrivateSuperClassField();
:
System.setSecurityManager(new SecurityManager() {
@Override
public void checkMemberAccess(Class<?> clazz, int which) {
if (clazz.equals(A.class)) {
throw new SecurityException();
} else {
super.checkMemberAccess(clazz, which);
}
}
});
Y hay otras condiciones bajo las cuales el enfoque de Reflexión no funcionará. Consulte la documentación de la API para SecurityManager y AccessibleObject para obtener más información. Gracias a CPerkins por señalarlo.
Espero que solo estuvieran probando tu conocimiento, no buscando una aplicación real de estas cosas ;-) Aunque creo que un truco feo como este puede ser legítimo en ciertos casos de ventaja.
A continuación se muestra el ejemplo para acceder a los miembros privados de superclase en el objeto de subclase.
Estoy usando constructores para hacer lo mismo.
A continuación se muestra la superclase de frutas.
public class Fruit {
private String type;
public Fruit() {
}
public Fruit(String type) {
super();
this.type = type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
A continuación se encuentra la subclase Guava que se hereda de Fruit.
public class Guava extends Fruit{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Guava(String name,String type) {
super(type);
this.name=name;
}
}
A continuación se muestra la función principal donde estamos creando un objeto de subclase y también mostrando el miembro de superclase.
public class Main {
public static void main(String[] args) {
Guava G1=new Guava("kanpuria", "red");
System.out.println(G1.getName()+" "+G1.getType());
}
}
Al usar el método de establecimiento, puede usar else con la ayuda de la reflexión, puede usar el miembro privado de la clase al hacer que el miembro diga a - tome una clase y establezca un a.setAccessible (verdadero);
De JLS §8.3. Declaraciones de campo :
Un campo privado de una superclase puede ser accesible a una subclase, por ejemplo, si ambas clases son miembros de la misma clase. Sin embargo, un campo privado nunca es heredado por una subclase.
Escribo el código de ejemplo:
public class Outer
{
class InnerA
{
private String text;
}
class InnerB extends InnerA
{
public void setText(String text)
{
InnerA innerA = this;
innerA.text = text;
}
public String getText()
{
return ((InnerA) this).text;
}
}
public static void main(String[] args)
{
final InnerB innerB = new Outer().new InnerB();
innerB.setText("hello world");
System.out.println(innerB.getText());
}
}
La explicación de la accesibilidad de InnerA.text
está aquí JLS §6.6.1. Determinación de la accesibilidad :
De lo contrario, el miembro o el constructor se declara privado, y el acceso está permitido si y solo si ocurre dentro del cuerpo de la clase de nivel superior (§7.6) que encierra la declaración del miembro o constructor.
Directamente no podemos acceder a ella. Pero usando Setter y Getter podemos acceder,
El código es:
class AccessPrivate1 {
private int a=10; //private integer
private int b=15;
int getValueofA()
{
return this.a;
}
int getValueofB()
{
return this.b;
}
}
public class AccessPrivate{
public static void main(String args[])
{
AccessPrivate1 obj=new AccessPrivate1();
System.out.println(obj.getValueofA()); //getting the value of private integer of class AccessPrivate1
System.out.println(obj.getValueofB()); //getting the value of private integer of class AccessPrivate1
}
}
El entrevistador estaba probando su conocimiento de los modificadores de acceso, o su enfoque para cambiar las clases existentes, o ambos.
Los habría incluido (público, privado, protegido, paquete privado) con una explicación de cada uno. Luego continúe diciendo que la clase A debería modificarse para permitir el acceso a esos miembros de la clase B, ya sea agregando establecedores y captadores o cambiando los modificadores de acceso de los miembros. O la clase B podría usar la reflexión. Finalmente, hable sobre las ventajas y desventajas de cada enfoque.
Es posible que desee cambiarlo a protegido. Por favor remítase esto
https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
Si esto es algo que tienes que hacer a cualquier costo solo por el simple hecho de hacerlo, puedes usar la reflexión. Le dará una lista de todas las variables definidas en la clase, ya sea pública, privada o protegida. Esto seguramente tiene su sobrecarga, pero sí, es algo que le permitirá utilizar variables privadas. Con esto, puedes usarlo en cualquiera de las clases. No tiene que ser solo una subclase. Consulte el siguiente ejemplo. Esto puede tener algunos problemas de compilación, pero puede obtener la idea básica y funciona
private void getPropertiesFromPrivateClass(){
Field[] privateVariablesArray = PrivateClassName.getClass().getDeclaredFields();
Set<String> propertySet = new HashSet<String>();
Object propertyValue;
if(privateVariablesArray.length >0){
for(Field propertyVariable :privateVariablesArray){
try {
if (propertyVariable.getType() == String.class){
propertyVariable.setAccessible(true);
propertyValue = propertyVariable.get(envtHelper);
System.out.println("propertyValue");
}
} catch (IllegalArgumentException illegalArgumentException) {
illegalArgumentException.printStackTrace();
} catch (IllegalAccessException illegalAccessException) {
illegalAccessException.printStackTrace();
}
}
Espero que esto sea de alguna ayuda. Feliz aprendizaje :)
Formas de acceder a los miembros privados de la superclase en subclase:
- Si desea acceso a paquetes, simplemente cambie los campos privados a protegidos. Permite el acceso a la misma subclase del paquete.
- Si tiene campos privados, simplemente proporcione algunos Métodos de acceso (captadores) y podrá acceder a ellos en su subclase.
También puede utilizar la clase interna, por ejemplo,
public class PrivateInnerClassAccess { private int value=20; class InnerClass { public void accessPrivateFields() { System.out.println("Value of private field : " + value); } } public static void main(String arr[]) { PrivateInnerClassAccess access = new PrivateInnerClassAccess(); PrivateInnerClassAccess.InnerClass innerClass = access.new InnerClass(); innerClass.accessPrivateFields(); } }
4. También puedes usar Reflexión, por ejemplo,
public class A { private int value; public A(int value) { this.value = value; } } public class B { public void accessPrivateA()throws Exception { A a = new A(10); Field privateFields = A.class.getDeclaredField("value"); privateFields.setAccessible(true); Integer value = (Integer)privateFields.get(a); System.out.println("Value of private field is :"+value); } public static void main(String arr[]) throws Exception { B b = new B(); b.accessPrivateA(); } }
La arquitectura está rota. Los miembros privados son privados porque no desea que se acceda a ellos fuera de la clase y amigos.
Puede usar hacks de amigos, accesores, promocionar al miembro o #define private public
(je). Pero todas estas son soluciones a corto plazo: es probable que en algún momento deba revisar la arquitectura rota.
Los modificadores son palabras clave que agrega a esas definiciones para cambiar su significado. El lenguaje Java tiene una amplia variedad de modificadores, incluidos los siguientes:
- Modificadores de acceso de Java
- Modificadores sin acceso
Para usar un modificador, incluya su palabra clave en la definición de una clase, método o variable. El modificador precede al resto de la sentencia.
Hay más información aquí:
http://tutorialcorejava.blogspot.in/p/java-modifier-types.html
Mediante el uso de accesores públicos (captadores y definidores) de los miembros privados de A ...
Mediante el uso de setters y getters u puede acceder a ella
No puede acceder a miembros privados desde la clase padre. Usted lo ha protegido o tiene un método protegido / público que tiene acceso a ellos.
EDITAR : Es cierto que puedes usar la reflexión. Pero eso no es habitual y no es buena idea romper la encapsulación.
No puedes acceder directamente a ninguna variable privada de una clase desde afuera directamente.
Puede acceder a los miembros privados utilizando getter y setter .
No sé sobre Java, pero en algunos lenguajes los tipos anidados pueden hacer esto:
class A {
private string someField;
class B : A {
void Foo() {
someField = "abc";
}
}
}
De lo contrario, utilice un método de acceso o un campo protected
(aunque a menudo se abusa de ellos).
Obviamente, la técnica preferida es hacerlos protegidos o agregar setters / getters. La reflexión es una opción desesperada.
Solo para mostrarle al entrevistador, SI "acceso" significa acceso de lectura, y si la Clase A genera XML o JSON, etc., puede serializar A y analizar los campos interesantes.
Para acceder a las variables privadas de la clase padre en la subclase, puede usar protegidas o agregar captadores y definidores a las variables privadas en la clase padre.
Privado estará oculto hasta que se le haya dado el acceso correcto. Por ejemplo Getters o setters por el programador que escribió el padre. Si tampoco son visibles por eso, entonces acepte el hecho de que solo son privados y no son accesibles para usted. ¿Por qué exactamente quieres hacer eso?
Puede usar Accessors (método de obtención y establecimiento) en su Código.
Puede usar los setters y los getters de la clase A. Lo que da la misma sensación que si estuviera usando el objeto de la clase A.
Se puede acceder a un miembro privado en una subclase de manera que no puede cambiar la variable, pero puede acceder a la variable como solo lectura.
Si estoy entendiendo la pregunta correctamente, puedes cambiar private
a protected
. Las variables protegidas son accesibles a las subclases, pero se comportan como variables privadas de lo contrario.
Tenga en cuenta que un campo privado de una superclase podría ser accesible a una subclase (por ejemplo, si ambas clases son miembros de la misma clase), Sin embargo, un campo privado nunca es heredado por una subclase
Una clase anidada puede acceder a todos los miembros privados de su clase adjunta, tanto los campos como los métodos. Por lo tanto, una clase anidada pública o protegida heredada por una subclase tiene acceso indirecto a todos los miembros privados de la superclase.
public class SuperClass
{
private int a = 10;
public void makeInner()
{
SubClass in = new SubClass();
in.inner();
}
class SubClass
{
public void inner()
{
System.out.println("Super a is " + a);
}
}
public static void main(String[] args)
{
SuperClass.SubClass s = new SuperClass().new SubClass();
s.inner();
}
}
Class A
{
private int i;
int getValue()
{
return i;
}
}
class B extends A
{
void getvalue2()
{
A a1= new A();
sop(a1.getValue());
}
}
- Los miembros privados no pueden ser accedidos en clase derivada
- Si desea acceder significa que puede usar los métodos de obtención y configuración.
class A
{
private int a;
void setA(int a)
{
this.a=a;
}
int getA()
{
return a;
}
}
Class B extends A
{
public static void main(String[] arg)
{
B obj= new B();
obj.setA(10);
System.out.println("The value of A is:"+obj.getA());
}
}