en tiempo de compilación Para su primera parte de la pregunta creo Wikipedia proporciona una buena definición:
En la programación orientada a objetos, el polimorfismo subtipo o inclusión polimorfismo es un concepto en la teoría de tipos en el que un nombre puede denotar instancias de de muchas clases diferentes, siempre que estén relacionadas por alguna clase común de . El polimorfismo de inclusión generalmente es soportado a través de la subtipificación, es decir, los objetos de diferentes tipos son completamente sustituibles por objetos de otro tipo (sus tipos base tipo (s)) y por lo tanto pueden manejarse a través de una interfaz común. Alternativamente, el polimorfismo de inclusión se puede lograr a través del tipo coerción, también conocido como tipo de fundición.
Otra Wikipedia llamada Polymorphism in object-oriented programming parece responder a sus preguntas muy bien. La segunda referencia en este artículo llamada On Understanding Types, Data Abstraction, and Polymorphism también cubre este asunto con gran detalle.
Esta función de subtipado en Java se logra, entre otros medios, a través de la herencia de clases e interfaces. Aunque las características de subtipado de Java pueden no ser evidentes en términos de herencia todo el tiempo. Tomemos, por ejemplo, los casos de covarianza y contravarianza con genéricos. Además, las matrices son serializables y clonables, aunque esto no es evidente en ninguna parte de la jerarquía de tipos. También se puede decir que a través de la conversión de ampliación primitiva, también los tipos numéricos en Java son polimórficos. Y el operador se comporta polimórficamente dependiendo de sus operandos.
En cualquier caso, la herencia juega un papel importante en la implementación de parte de este polimorfismo.
sobrecarga vs Anulación
Su segunda parte de la pregunta parece ser sobre la elección de la implementación de un método dado. Evidentemente, si una clase anula un método y usted crea una instancia de esa clase, quiere que se invoque la versión anulada del método, incluso si está accediendo al objeto a través de una referencia de la clase padre.
La selección de la implementación correcta del método se realiza en tiempo de ejecución como bien indicó, ahora la firma del método que se va a invocar se decide en tiempo de compilación. Como la sobrecarga se trata de diferentes métodos con el mismo nombre y una firma diferente, es por eso que se dice que la selección del método de anulación ocurre en el momento de la compilación.
Anulación Método de selección en tiempo de compilación
El Java Language Specification (JLS) en la sección 15.12 Method Invocation Expressions explica en detalle el proceso que sigue el compilador para elegir el método adecuado para invocar.
Allí observará que se trata de una tarea en tiempo de compilación. El JLS dice en el párrafo 15.12.2:
Este paso utiliza el nombre del método y los tipos de argumento expresiones de para localizar métodos que son a la vez accesible y aplicable Puede haber más de uno de esos métodos, en cuyo caso se elige el más específico.
Para verificar la naturaleza del tiempo de compilación de esto, puede hacer la siguiente prueba.
Declara una clase como esta y compilala.
public class ChooseMethod {
public void doSomething(Number n){
System.out.println("Number");
}
}
Declara una segunda clase que invoca un método del primero y lo compila.
public class MethodChooser {
public static void main(String[] args) {
ChooseMethod m = new ChooseMethod();
m.doSomething(10);
}
}
Si se invoca el principal, la salida dice Number
.
Ahora, agregue un segundo más específica sobrecargado método a la clase ChooseMethod
y compilarlo (pero no vuelva a compilar la otra clase).
public void doSomething(Integer i) {
System.out.println("Integer");
}
Si ejecuta el principal nuevo, la salida sigue siendo Number
.
Básicamente, porque se decidió en tiempo de compilación. Si vuelve a compilar la clase MethodChooser
(la que tiene la principal) y vuelve a ejecutar el programa, la salida será Integer
.
Como tal, si desea forzar la selección de uno de los métodos sobrecargados, el tipo de argumentos debe corresponderse con el tipo de parámetros en tiempo de compilación, y no solo en tiempo de ejecución.
Anulación Método de selección en tiempo de ejecución
Una vez más, la firma del método se decide en tiempo de compilación, pero la implementación real se decide en tiempo de ejecución.
Declara una clase como esta y compilala.
public class ChooseMethodA {
public void doSomething(Number n){
System.out.println("Number A");
}
}
Entonces declarar una segunda clase que se extiende y compilar:
public class ChooseMethodB extends ChooseMethodA { }
Y en la clase MethodChooser haces:
public class MethodChooser {
public static void main(String[] args) {
ChooseMethodA m = new ChooseMethodB();
m.doSomething(10);
}
}
Y si lo ejecuta se obtiene la salida Number A
, y esto está bien, porque el método no ha sido anulado en ChooseMethodB
y, por lo tanto, la implementación que se invoca es la de ChooseMethodA
.
Ahora, agregue un método sobreescrito en MethodChooserB
:
public void doSomething(Number n){
System.out.println("Number B");
}
y recompilar solo este, y ejecute el método principal de nuevo.
Ahora, se obtiene la salida Number B
Como tal, la ejecución fue elegido en tiempo de ejecución, y se requiere no recompilación de la clase MethodChooser
.
Creo que la sobrecarga no tiene nada que ver con el polimorfismo. – ka3ak
En realidad, esta es una forma de polimorfismo: de Wikipedia: el término polimorfismo ad-hoc para referirse a funciones polimórficas que se pueden aplicar a argumentos de diferentes tipos, pero que se comportan de manera diferente según el tipo de argumento al que se aplican (también conocido como sobrecarga de funciones o sobrecarga del operador) .. –
@edalorzo: se disputa la exactitud de los hechos de http://en.wikipedia.org/wiki/Ad-hoc_polymorphism. – Jayan