valor salida referencia por paso pasar parámetros parametros herencia entero ejemplos java oop inheritance

salida - pasar entero por referencia java



Explicar cómo funciona la ocultación de variables en este código Java. (5)

Bueno, esto es debido a la unión estática.

1) El enlace estático en Java se produce durante el tiempo de compilación, mientras que el enlace dinámico se produce durante el tiempo de ejecución.

2) Los métodos privados, los métodos finales y los métodos y variables estáticos utilizan el enlace estático y el enlace del compilador, mientras que los métodos virtuales se enlazan durante el tiempo de ejecución en función del objeto de tiempo de ejecución.

3) El enlace estático utiliza información de tipo (clase en Java) para el enlace, mientras que el enlace dinámico utiliza el objeto para resolver el enlace.

4) Los métodos sobrecargados se enlazan mediante un enlace estático, mientras que los métodos sobrescritos se unen mediante un enlace dinámico en tiempo de ejecución.

Considera el siguiente código

class A { int x = 5; void foo() { System.out.println(this.x); } } class B extends A { int x = 6; // some extra stuff } class C { public static void main(String args[]) { B b = new B(); System.out.println(b.x); System.out.println(((A)b).x); b.foo(); } }

La salida del programa es

6 5 5

Entiendo los dos primeros, pero no puedo entender el último. ¿Cómo se imprime b.foo ()? 5. La clase B heredará el método foo. ¿Pero no debería imprimir lo que bx imprimiría? ¿Qué está sucediendo exactamente aquí?


Cuando usted llama

b.foo();

Comprueba si B ha anulado el método foo() , que no lo ha hecho. Luego mira un nivel hacia arriba, a la superclase A e invoca ese método.

Luego ha invocado la versión de A de foo() que luego se imprime.

this.x

Ahora, A no puede ver la versión de B de x .

Para resolver esto, tienes que anular el método en B

class B extends A { int x = 6; @Override void foo() { System.out.println(this.x); } }

Ahora llamando

b.foo();

llamará a la versión de B de foo() y obtendrá el resultado esperado.


En JAVA , los métodos pueden ser anulados mientras que las variables no pueden. Entonces, como su método foo no se anula en B , toma la variable miembro de A


Los campos no son anulables en Java y las subclases con los mismos nombres de campo que la clase principal, sombrean "solo" los campos de la clase principal.
Entonces, this.x refiere a la x definida en la clase actual: A
Mientras que el resultado: 5 .

Para ser más precisos: el método foo() es heredado por la subclase B pero esto no significa que el comportamiento del método heredado cambiará en los campos de instancia a los que se hace referencia, ya que dichos campos no son reemplazables: la expresión this.x que hace referencia el campo Ax en el método foo() continúa haciendo referencia a Ax .

Es exactamente lo mismo que para las dos afirmaciones anteriores:

B b = new B(); System.out.println(b.x); // refers B.x -> 6 System.out.println(((A)b).x); // refers A.x -> 5 b.foo(); // refers under the hood A.x -> 5

La muy buena respuesta de rgettman muestra cómo puede superar el campo que se oculta en la subclase.
Una alternativa para superar la ocultación se basa en hacer que el campo de instancia sea private (que se recomienda) y proporcionar un método que devuelva el valor.
De esta manera, se beneficia del mecanismo de anulación y la ocultación de campos ya no es un problema para los clientes de las clases:

class A { private int x = 5; int getX(){ return x; } void foo() { System.out.println(this.getX()); } } class B extends A { private int x = 6; int getX(){ return x; } }


Sí, la clase B hereda el método foo . Pero la variable x en B oculta la x en A ; no lo reemplaza

Este es un tema de alcance. El método foo en A solo ve las variables que están en el alcance. La única variable en el alcance es la variable de instancia x en A

El método foo se hereda, pero no se invalida, en B Si tuvieras que anular explícitamente foo con el mismo código exacto:

class B extends A { int x = 6; @Override void foo() { System.out.println(this.x); } }

Entonces la variable que estaría en el alcance cuando se hace referencia por this.x sería la x B , y se imprimirían 6 . Si bien el texto del método es el mismo, la referencia es diferente debido al alcance.

Por cierto, si realmente quería referirse a la x en la clase B , puede usar super.x .