Teniendo una estructura de herencia
Donde
- Tenemos isBiped overriden en Kangaroo
- Kangaroo hereda el metodo getMarsupialDescription
Si implementamos la siguiente logica en el main de Kangaroo
public class Marsupial {
public boolean isBiped() {
return false;
}
public void getMarsupialDescription() {
System.out.println("Marsupial walks on two legs: " + isBiped());
}
}
class Kangaroo extends Marsupial {
public boolean isBiped() {
return true;
}
public void getKangarooDescription() {
System.out.println("Kangaroo hops on two legs: " + isBiped());
}
public static void main(String[] args) {
Marsupial marsupialOne = new Marsupial();
marsupialOne.getMarsupialDescription();
marsupialOne.getKangarooDescription();
// Marsupial Ref, Kangaroo obj
Marsupial marsupialTwo = new Kangaroo();
marsupialTwo.getMarsupialDescription();
marsupialTwo.getKangarooDescription();
// Kangaroo Ref & obj
Kangaroo kangaroo = new Kangaroo();
kangaroo.getMarsupialDescription();
kangaroo.getKangarooDescription();
}
}
$ javac Marsupial.java
Marsupial.java:27: error: cannot find symbol
marsupialOne.getKangarooDescription();
^
symbol: method getKangarooDescription()
location: variable marsupialOne of type Marsupial
Marsupial.java:32: error: cannot find symbol
marsupialTwo.getKangarooDescription();
^
symbol: method getKangarooDescription()
location: variable marsupialTwo of type Marsupial
2 errors
Tratando de explicar este resultado debo primero lanzar una hipotesis de lo que esta haciendo la JVMAl compilar
Marsupial marsupialOne = new Marsupial();
marsupialOne.getMarsupialDescription();
marsupialOne.getKangarooDescription();
Al ser marsupial una referencia tipo Marsupial, el compilador busca en esta clase la definicion de los metodos getMarsupialDescription y getKangarooDescription, y solamente encuentra el primero, el segundo no esta definido en esta clase por lo cual arroja el primer error
Para el caso:
Marsupial marsupialTwo = new Kangaroo();
marsupialTwo.getMarsupialDescription();
marsupialTwo.getKangarooDescription();
En este caso aunque el objeto es de tipo Kangaroo, la referencia en la que se almacena es de tipo Marsupial, el compilador, entonces, busca en esta clase la definicion de los metodos getMarsupialDescription y getKangarooDescription, y solamente encuentra el primero, el segundo no esta definido en esta clase por lo cual arroja el segundo error
En tiempo de compilacion aun no existe ningun objeto, asi que la JVM se limita a examinar la definicion de las clases
Kangaroo kangaroo = new Kangaroo();
kangaroo.getMarsupialDescription();
kangaroo.getKangarooDescription();
kangaroo es un objeto de tipo Kangaroo, la referencia en la que se almacena es de tipo Kangaroo, el compilador, entonces, busca en esta clase la definicion de los metodos getMarsupialDescription y getKangarooDescription, y solamente encuentra el segudno, el primero no esta definido en esta clase, entonces, busca en la clase padre, donde si encuentra la definicion y da por valida la sentencia
Se puede corregir los errores removiendo las lineas
marsupialOne.getKangarooDescription();
...
marsupialTwo.getKangarooDescription();
Output:
Marsupial walks on two legs: false
Marsupial walks on two legs: true
Marsupial walks on two legs: true
Kangaroo hops on two legs: true
Sabiendo que getMarsupialDescription llama al metodo isBiped, ¿porque hay resultados diferentes en marsupialOne y marsupialTwo?
La respuesta es que marsupialOne es un objeto de tipo Marsupial y y marsupialTwo es un objeto Kagaroo, y estas clases tienen su propia implementacion del metodo isBiped, a la cual llaman respectivamente
Que ocurre si cambiamos la implementacion de isBiped a static en las dos classes
public static boolean isBiped()
Marsupial walks on two legs: false
Marsupial walks on two legs: false
Marsupial walks on two legs: false
Kangaroo hops on two legs: true
En este caso, al ser isBiped un metodo estatico esta vinculado al tipo de referencia, no al objeto, asi, cuando se llama getMarsupialDescription usando una referencia Marsupial, se llama al metodo estatico isBiped de esa clase en particular