2.3 Polimorfismo - ajpaez/OCA GitHub Wiki
(OCA Objectives 7.2 and 7.3)
Un objeto polimórfico es aquel que pase el test IS-A con mas de una clase. Todos los objetos son polimórficos en Java, excepto Object, ya que pasan el test con su propia clase y con la clase Object. Recuerda que solo se tiene acceso a un objeto a través de su variable de referencia. Claves sobre las referencias:
- Una variable de referencia puede ser solo de un tipo, y una vez declarado ese tipo nunca puede ser cambio, aunque el objeto al que hace referencia se pueda cambiar
- Una variable de referencia, puede ser reasignada a otro objeto, aunque la referencia sea declarada como final.
- El tipo de la variable de referencia determina los métodos que pueden ser invocados desde el objeto al que la variable hace referencia.
- Una variable de referencia puede referirse a cualquier objeto del mismo tipo que el declarado en la referencia o a cualquier subtipo de declarado.
- Una variable de referencia puede ser declarada como un tipo de clase o un tipo de interfaz.
JAVA NO soporta la herencia múltiple!!!
Continuando con el ejemplo anterior:
class GameShape {
public void displayShape() {
System.out.println("displaying shape");
}
// more code
}
class PlayerPiece extends GameShape {
public void movePiece() {
System.out.println("moving game piece");
}
// more code
}
class TilePiece extends GameShape {
public void getAdjacent() {
System.out.println("getting adjacent tiles");
}
// more code
}
Imaginemos que necesitamos dar un nuevo comportamiento la clase PlayerPiece, podemos añadirlo a GameShape, pero lo heredaría también TilePiece y eso no es lo que queremos, por tanto la solución pasa por crear una nueva interfaz y que solo la clase PlayerPiece la implemente.
public interface Animatable {
public void animate();
}
class PlayerPiece extends GameShape implements Animatable {
public void movePiece() {
System.out.println("moving game piece");
}
public void animate() {
System.out.println("animating...");
}
// more code
}
Ahora la clase PlayerPiece pasa el test IS-A para la clase GameSHape y la interfaz Animatable. Esto significa que la clase PlayerPiece puede ser tratada polimórficamente como una de las cuatro cosas en un momento dado, dependiente del tipo de variable de referencia declarado:
- Como un Object
- Como un GameShape
- Como un PalyerPiece
- Como un Animatable
Lo vemos en código:
PlayerPiece player = new PlayerPiece();
Object o = player;
GameShape shape = player;
Animatable mover = player;
Solo hay un objeto aquí, una instancia del tipo PlayerPiece, pero hay cuatro tipo diferentes de variables de referencia, todos apuntando al mismo objeto en el heap.
En tiempo de compilación, una variable de referencia del tipo GameShape, solo conoce los métodos de GameShape, pero en tiempo de ejecución, la JVM, reconoce realmente el objeto al que hace referencia y si una variable de referencia de tipo GameShape hace referencia a una instancia de tipo PlayerPiece y este ultimo sobrescribe el método que heredó de GameShape se ejecutará el de la instancia creada.
NOTA: El polimorfismo solo aplica a los métodos de instancias, son los únicos miembros de un objeto que en tiempo de ejecución se seleccionan de forma dinámica basándose en el objeto real.
!!! El polimorfismo no aplica a métodos estáticos ni a variables estáticas. !!!
Virtual call
Una llamada virtual a un método significa que la invocación a este se realiza en tiempo de ejecución y no en tiempo de compilación. En Java, todas las llamadas de métodos de instancia no-privadas y no-finales son virtuales. Esto es importante porque, en tiempo de ejecución, una variable de referencia puede apuntar a una instancia de una subclase de la clase de la referencia. El compilador no tiene el conocimiento de la clase del objeto real a la que se refiere la variable de referencia. Si la subclase sobreescribe el método, la llamada se vuelve polimórfica porque ahora hay dos versiones del método que se pueden invocar (la versión de clase base y la versión de subclase). Por lo tanto, el compilador no puede vincular la llamada al método de una clase específica. Sólo la JVM tiene la información necesaria para enlazar la llamada. La JVM conoce la clase del objeto real y enlaza la llamada al método de esa clase ( lo que se conoce como polimorfismo). Por lo tanto, en Java, todas las llamadas de método de instancia no-privadas y no-finales son potencialmente polimórficas porque podría haber múltiples versiones del método elegibles para ser invocadas.