ventajas sobre programacion polimorfismo orientada objetos mapa ejercicios clases caracteristicas abstractas java polymorphism overloading override method-dispatch

programacion - todo sobre polimorfismo java



La sobrecarga es un polimorfismo en tiempo de compilación. De Verdad? (4)

¿Qué es el polimorfismo?

Acc. para mí : si una entidad puede representarse en más de una forma, se dice que esa entidad exhibe polimorfismo.

Ahora, apliquemos esta definición a las construcciones de Java:

1) La sobrecarga del operador es un polimorfismo de tiempo de compilación.

Por ejemplo, el operador + se puede usar para agregar dos números O para concatenar dos cadenas. Es un ejemplo de polimorfismo que dice estrictamente el polimorfismo en tiempo de compilación.

2) La sobrecarga de métodos es el polimorfismo de tiempo de compilación.

Por ejemplo, un método con el mismo nombre puede tener más de una implementación. También es un polimorfismo en tiempo de compilación.

It''s compile-time because before execution of program compiler decides the flow of program ie which form will be used during run-time.

3) La anulación del método es el polimorfismo en tiempo de ejecución.

Por ejemplo, un método con la misma firma puede tener más de una implementación. Es un polimorfismo de tiempo de ejecución.

4) El uso de la clase base en lugar de la clase derivada es el polimorfismo de tiempo de ejecución.

Por ejemplo, una referencia de interface puede apuntar a cualquiera de sus implementadores.

It''s run-time because the flow of program can''t be known before execution ie only during run-time it can be decided that which form will be used.

Espero que se aclare un poco.

Sé la diferencia sintáctica entre anular y sobrecargar. Y también sé que anular es el polimorfismo en tiempo de ejecución y la sobrecarga es un polimorfismo en tiempo de compilación. Pero mi pregunta es: ¿la sobrecarga es realmente un polimorfismo en tiempo de compilación? Para aclarar mi punto, consideremos una clase de ejemplo.

public class Greeter { public void greetMe() { System.out.println("Hello"); } public void greetMe(String name) { System.out.println("Hello " + name); } public void wishLuck() { System.out.println("Good Luck"); } }

Dado que todos los métodos greetMe(), greetMe(String name), wishLuck() son públicos, todos pueden ser anulados (incluido uno sobrecargado), ¿verdad? Por ejemplo,

public class FancyGreeter extends Greeter { public void greetMe() { System.out.println("***********"); System.out.println("* Hello *"); System.out.println("***********"); } }

Ahora, considere el siguiente fragmento de código:

Greeter greeter = GreeterFactory.getRandomGreeter(); greeter.greetMe();

El método getRandomGreeter() devuelve un objeto Greeter aleatorio. Puede devolver un objeto de Greeter , o cualquiera de sus subclases, como FancyGreeter o GraphicalGreeter o cualquier otra. getRandomGreeter() creará los objetos usando un archivo de clase new o dinámicamente, y creará un objeto usando la reflexión (creo que es posible con la reflexión) o de cualquier otra forma que sea posible. Todos estos métodos de Greeter pueden o no ser anulados en subclases. Por lo tanto, el compilador no tiene forma de saber si un método en particular (sobrecargado o no) está anulado. ¿Derecha? Además, wikipedia dice en funciones virtuales :

En Java, todos los métodos no estáticos son por defecto "funciones virtuales". Solo los métodos marcados con la palabra clave final, que no se pueden anular, junto con los métodos privados, que no se heredan, son no virtuales.

Dado que, las funciones virtuales se resuelven en tiempo de ejecución mediante el envío dinámico de métodos, y como todos los métodos no privados y no finales son virtuales (estén sobrecargados o no), deben resolverse en tiempo de ejecución. ¿Derecha?

Entonces, ¿cómo se puede resolver la sobrecarga en tiempo de compilación? O, ¿hay algo que haya malinterpretado, o me estoy perdiendo?


Cada clase de ''Greeter'' tiene 3 métodos virtuales: void greetMe() , void greetMe(String) y void wishLuck() .

Cuando llama a greeter.greetMe() el compilador puede determinar cuál de los tres métodos virtuales debería llamarse desde la firma del método, es decir. the void greetMe() one ya que no acepta argumentos. La implementación específica del método void greetMe() se llama depende del tipo de la instancia de greeter y se resuelve en tiempo de ejecución.

En su ejemplo, es trivial que el compilador determine a qué método llamar, ya que las firmas del método son completamente diferentes. Un ejemplo ligeramente mejor para mostrar el concepto de ''polimorfismo de tiempo de compilación'' podría ser el siguiente:

class Greeter { public void greetMe(Object obj) { System.out.println("Hello Object!"); } public void greetMe(String str) { System.out.println("Hello String!"); } }

El uso de esta clase de saludos dará los siguientes resultados:

Object obj = new Object(); String str = "blah"; Object strAsObj = str; greeter.greetMe(obj); // prints "Hello Object!" greeter.greetMe(str); // prints "Hello String!" greeter.greetMe(strAsObj); // prints "Hello Object!"

El compilador seleccionará el método con la coincidencia más específica utilizando el tipo de tiempo de compilación, por lo que el segundo ejemplo funciona y llama al void greetMe(String) .

La última llamada es la más interesante: a pesar de que el tipo de tiempo de ejecución de strAsObj es String , se ha convertido en un Object así es como lo ve el compilador. Por lo tanto, la coincidencia más cercana que el compilador puede encontrar para esa llamada es el void greetMe(Object) .


La sobrecarga a este respecto significa que el tipo de función se determina estáticamente en el momento de la compilación en lugar del envío dinámico.

Lo que realmente sucede detrás de escena es que para un método llamado "foo" con los tipos "A" y "B" se crean dos métodos ("foo_A" y "foo_B"). A cuál de ellos se va a llamar se determina en el momento de compilación (objeto foo((A) object) o foo((B) object) resultado de que se foo_A a foo_A o foo_B ). En cierto modo, esto es un polimorfismo en tiempo de compilación, aunque el método real (es decir, qué implementación en la jerarquía de clases a tomar) se determina en el tiempo de ejecución.


Los métodos sobrecargados aún pueden ser anulados, si eso es lo que pides.

Los métodos sobrecargados son como familias diferentes, aunque comparten el mismo nombre. El compilador elige estáticamente una familia dada la firma, y ​​luego, en tiempo de ejecución, se envía al método más específico en la jerarquía de clases.

Es decir, el envío de métodos se realiza en dos pasos:

  • El primero se realiza en tiempo de compilación con la información estática disponible, el compilador emitirá una call para la firma que coincida mejor con los parámetros de su método actual entre la lista de métodos sobrecargados en el tipo declarado del objeto sobre el que se invoca el método.
  • El segundo paso se realiza en tiempo de ejecución, dada la firma del método que debe llamarse (paso anterior, ¿recuerda?), La JVM lo enviará a la versión anulada más concreta en el tipo real de objeto receptor.

Si los tipos de argumentos de método no son covariantes en absoluto, la sobrecarga es equivalente a tener los nombres de los métodos modificados en el momento de la compilación; Debido a que son métodos efectivamente diferentes, la JVM nunca los enviará indistintamente según el tipo de receptor.