Tengo el siguiente código:
package testapp;
class Calculation {
public Calculation(){}
public void addition(int x, int y) { }
public void Subtraction(int x, int y) { }
}
class My_Calculation extends Calculation {
public My_Calculation(){}
public void multiplication(int x, int y) { }
}
public class TestApp {
public static void main(String[] args) {
int a = 20, b = 10;
My_Calculation demo = new My_Calculation();
demo.addition(a, b);
demo.Subtraction(a, b);
demo.multiplication(a, b);
System.out.println(demo.getClass().getName());
Calculation d = new Calculation();
d.Subtraction(b, b);
d.addition(b, b);
// no multiplication
System.out.println(d.getClass().getName());
Calculation d2 = new My_Calculation();
d2.Subtraction(b, b);
d2.addition(b, b);
// no multiplication
System.out.println(d2.getClass().getName());
}
}
La salida es la siguiente:
Demo = testapp.My_Calculation
d = testapp.Calculation
d2 = testapp.My_Calculation
La siguiente declaración es una declaración de que el nombre variable de referencias d2 de tipo de objeto de cálculo :
Calculation d2;
La siguiente declaración es una inicialización que llama constructor My_Calculation.
Calculation d2 = new My_Calculation();
Cuando ejecuto el siguiente código, la salida indica que d2 es del tipo de clase My_Calculation sino que da acceso a los métodos dentro de la clase de cálculo .
System.out.println(d2.getClass().getName());
Salida: testapp.My_Calculation
Acceso: adición; sustracción
Ahora, mi entendimiento me dice que si My_Calculation se llama al constructor que debería tener ya sea:
1. Acceso a exclusivamente a la reproducción, o
2. Acceso a la suma, resta y multiplicación.
Pero, de hecho me da la inversa: el acceso a la suma y la resta SOLAMENTE . Por lo tanto, veo esto como contrario a la intuición.
Podría alguien explicarme lo que está sucediendo aquí para dar una comprensión coherente de por qué un objeto de tipo: My_Calculation no tendría acceso a sus propios métodos , pero el acceso a sólo los métodos superclases .
Aquí:
Calculation d2 = new My_Calculation();
Se crea un objeto de tipo My_Calculation
, pero que se le asigna a una variable declarada con el supertipo! Y el compilador no es lo suficientemente inteligente como para "ver" que d2
es en realidad el tipo de niño. Así, los compiladores le impide llamar a un método definido en ese tipo de niños. Debido a que el compilador, d2
se sabe que es una Calculation
!
Tenga en cuenta que se puede echar a decirle al compilador "Yo sé mejor":
( (My_Calculation) d2) ).multiplication(...
que trabajaría en tiempo de compilación, y también en tiempo de ejecución!
Su idea errónea comienza aquí:
Calculation d2 = new My_Calculation();
Lo que se hace en el lado derecho de la asignación es básicamente "olvidado" en la siguiente línea. A continuación, el compilador sólo se sabe que tiene algún d2
tipo Calculation
!
Por último: si, en su específica ejemplo, el compilador podría fácilmente determinar el verdadero tipo de d2
. Sin embargo, hay muchas situaciones en las que no es fácil, o incluso imposible. Por lo tanto las personas que están detrás de Java decidieron ignorar tales "conocimiento" potencial.