la palabra polimorfismo se usa en varios contextos y describe situaciones en las que algo ocurre en varias formas diferentes. En informática, describe el concepto de que se puede acceder a objetos de diferentes tipos a través de la misma interfaz. Cada tipo puede proporcionar su propia implementación independiente de esta interfaz. Es uno de los conceptos centrales de la programación orientada a objetos (OOP).,
si se pregunta si un objeto es polimórfico, puede realizar una prueba simple. Si el objeto pasa con éxito varias pruebas is-a o instanceof, es polimórfico. Como he descrito en mi post sobre herencia, todas las clases Java extienden el objeto de clase. Debido a esto, todos los objetos en Java son polimórficos porque pasan al menos dos comprobaciones instanceof.,
diferentes tipos de polimorfismo
Java soporta 2 tipos de polimorfismo:
- static or compile-time
- dynamic
Static polymorphism
Java, al igual que muchos otros lenguajes de programación orientados a objetos, le permite implementar múltiples métodos dentro de la misma clase que usan el mismo nombre pero un conjunto diferente de parámetros. Eso se llama sobrecarga del método y representa una forma estática de polimorfismo.,
los conjuntos de parámetros tienen que diferir en al menos uno de los siguientes tres criterios:
- necesitan tener un número diferente de parámetros, por ejemplo, un método Acepta 2 y otro 3 parámetros.
- Los tipos de los parámetros deben ser diferentes, por ejemplo, un método acepta una cadena y otro un largo.
- necesitan esperar los parámetros en un orden diferente, por ejemplo, un método acepta una cadena y una larga y otro acepta una cadena larga y una cadena. Este tipo de sobrecarga no se recomienda porque hace que la API sea difícil de entender.,
en la mayoría de los casos, cada uno de estos métodos sobrecargados proporciona una funcionalidad diferente pero muy similar.
debido a los diferentes conjuntos de parámetros, cada método tiene una firma diferente. Esto permite al compilador identificar qué método tiene que ser llamado y vincularlo a la llamada al método. Este enfoque se denomina unión estática o polimorfismo estático.
echemos un vistazo a un ejemplo.
un ejemplo simple de polimorfismo estático
utilizo el mismo proyecto CoffeeMachine que utilicé en los posts anteriores de esta serie. Puede clonarlo en https://github.com/thjanssen/Stackify-OopInheritance.,
La Clase BasicCoffeeMachine implementa dos métodos con el nombre brewCoffee. El primero acepta un parámetro de tipo CoffeeSelection. El otro método acepta dos parámetros, una CoffeeSelection y una int.
ahora, cuando se llama a uno de estos métodos, el conjunto de parámetros proporcionado identifica el método que tiene que ser llamado.
en el siguiente fragmento de código, llamo al método solo con un objeto CoffeeSelection. En tiempo de compilación, el compilador Java enlaza esta llamada al método brewCoffee(CoffeeSelection selection).,
BasicCoffeeMachine coffeeMachine = createCoffeeMachine();coffeeMachine.brewCoffee(CoffeeSelection.FILTER_COFFEE);
Si Cambio este código y llamo al método brewCoffee con un objeto CoffeeSelection y un int, el compilador enlaza la llamada al método con el otro método brewCoffee(CoffeeSelection selection, int number).
polimorfismo Dinámico
esta forma de polimorfismo no permite al compilador determinar el método ejecutado. La JVM necesita hacer eso en tiempo de ejecución.
dentro de una jerarquía de herencia, una subclase puede anular un método de su superclase. Esto permite al desarrollador de la subclase personalizar o reemplazar completamente el comportamiento de ese método.,
también crea una forma de polimorfismo. Ambos métodos, implementados por la superclase y la subclase, comparten el mismo nombre y parámetros, pero proporcionan una funcionalidad diferente.
echemos un vistazo a otro ejemplo del proyecto CoffeeMachine.
sobreescritura de método en una jerarquía de herencia
La Clase BasicCoffeeMachine es la superclase de la clase PremiumCoffeeMachine.
ambas clases proporcionan una implementación del método brewCoffee (selección CoffeeSelection).,
si lees el post sobre la herencia del concepto OOP, ya conoces las dos implementaciones del método brewCoffee. La máquina BasicCoffeeMachine solo admite la selección de cafés.FILTER_COFFEE. El método brewCoffee de la clase PremiumCoffeeMachine agrega soporte para CoffeeSelection.ESPRESSO. Si se llama con cualquier otra CoffeeSelection, utiliza la palabra clave super para delegar la llamada a la superclase.,
late binding
Cuando desee utilizar una jerarquía de herencia de este tipo en su proyecto, debe poder responder a la siguiente pregunta: ¿a qué método llamará la JVM?
que solo se puede responder en tiempo de ejecución porque depende del objeto en el que se llama al método. El tipo de referencia, que puedes ver en tu código, es irrelevante. Es necesario distinguir tres escenarios generales:
- Su objeto es del tipo de la superclase y se hace referencia como la superclase., Por lo tanto, en el ejemplo de este post, un objeto BasicCoffeeMachine se hace referencia como un BasicCoffeeMachine.
- Su objeto es del tipo de la subclase y se hace referencia como la subclase. En el ejemplo de este post, se hace referencia a un objeto PremiumCoffeeMachine como PremiumCoffeeMachine.
- Su objeto es del tipo de la subclase y se hace referencia como la superclase. En el ejemplo CoffeeMachine, se hace referencia a un objeto PremiumCoffeeMachine como BasicCoffeeMachine.
superclase referenciada como la superclase
el primer escenario es bastante simple., Cuando instancie un objeto BasicCoffeeMachine y lo almacene en una variable de tipo BasicCoffeeMachine, la JVM llamará al método brewCoffee en la clase BasicCoffeeMachine. Así que sólo puedes preparar una selección de café.FILTER_COFFEE.
Subclase referenciada como la subclase
el segundo escenario es similar. Pero esta vez, instancio una PremiumCoffeeMachine y la referencia como una PremiumCoffeeMachine. En este caso, la JVM llama al método brewCoffee de la clase PremiumCoffeeMachine, que agrega soporte para CoffeeSelection.ESPRESSO.,
Subclase referenciada como superclase
Este es el escenario más interesante y la razón principal por la que explico el polimorfismo dinámico en tales detalles.
Cuando crea una instancia de un objeto PremiumCoffeeMachine y lo asigna a la variable basiccoffeemachine coffeeMachine, sigue siendo un objeto PremiumCoffeeMachine. Parece una máquina de café básica.
el compilador no ve eso en el código, y solo puede usar los métodos proporcionados por la clase BasicCoffeeMachine., Pero si llama al método brewCoffee en la variable coffeeMachine, la JVM sabe que es un objeto de tipo PremiumCoffeeMachine y ejecuta el método anulado. Esto se llama enlace tardío.
resumen
El polimorfismo es uno de los conceptos centrales en los lenguajes de programación orientada a objetos. Describe el concepto de que se pueden usar diferentes clases con la misma interfaz. Cada una de estas clases puede proporcionar su propia implementación de la interfaz.
Java soporta dos tipos de polimorfismo. Puede sobrecargar un método con diferentes conjuntos de parámetros., Esto se llama polimorfismo estático porque el compilador enlaza estáticamente la llamada al método a un método específico.
dentro de una jerarquía de herencia, una subclase puede anular un método de su superclase. Si instancias la subclase, la JVM siempre llamará al método anulado, incluso si envías la subclase a su superclase. Eso se llama polimorfismo dinámico.