- Polimorfismo (informática)
-
En programación orientada a objetos el polimorfismo se refiere a la capacidad para que varias clases derivadas de una antecesora utilicen un mismo método de forma diferente.
Por ejemplo, podemos crear dos clases distintas: Pez y Ave que heredan de la superclase Animal. La clase Animal tiene el método abstracto mover que se implementa de forma distinta en cada una de las subclases (peces y aves se mueven de forma distinta).
Como se mencionó anteriormente, el concepto de polimorfismo se puede aplicar tanto a funciones como a tipos de datos. Así nacen los conceptos de funciones polimórficas y tipos polimórficos. Las primeras son aquellas funciones que pueden evaluarse o ser aplicadas a diferentes tipos de datos de forma indistinta; los tipos polimórficos, por su parte, son aquellos tipos de datos que contienen al menos un elemento cuyo tipo no está especificado.
Contenido
Clasificación
Se puede clasificar el polimorfismo en dos grandes clases:
Polimorfismo dinámico (o polimorfismo paramétrico) es aquél en el que el código no incluye ningún tipo de especificación sobre el tipo de datos sobre el que se trabaja. Así, puede ser utilizado a todo tipo de datos compatible. Polimorfismo estático (o polimorfismo ad hoc) es aquél en el que los tipos a los que se aplica el polimorfismo deben ser explicitados y declarados uno por uno antes de poder ser utilizados.
El polimorfismo dinámico unido a la herencia es lo que en ocasiones se conoce como programación genérica.
También se clasifica en herencia por redefinición de métodos abstractos y por método sobrecargado. El segundo hace referencia al mismo método con diferentes parámetros.
Otra clasificación agrupa los polimorfismo en dos tipos: Ad-Hoc que incluye a su vez sobrecarga de operadores y coerción, Universal (inclusión o controlado por la herencia, paramétrico o genericidad).
Ejemplo de polimorfismo
En este ejemplo haremos uso del lenguaje C++ para mostrar el polimorfismo. También se hará uso de las funciones virtuales puras de este lenguaje, aunque para que el polimorfismo funcione no es necesario que las funciones sean virtuales puras, es decir, perfectamente el código de la clase "superior" (en nuestro caso 'figura') podría tener código.
#include<iostream> using namespace std; class figura { private: float base; float altura; public: void captura(); virtual unsigned float perimetro()=0; virtual unsigned float area()=0; }; class rectangulo: public figura{ public: void imprime(); unsigned float perimetro(){return 2*(base+altura);} unsigned float area(){return base*altura;} }; class triangulo: public figura{ public: void muestra(); unsigned float perimetro(){return 2*altura+base} unsigned float area(){return (base*altura)/2;} }; void figura::captura(){ cout<<"CALCULO DEL AREA Y PERIMETRO DE UN TRIANGULO ISÓSCELES Y UN RECTANGULO:" <<endl; cout<<"escribe la altura: "; cin>>altura; cout<<"escribe la base: "; cin>>base; cout<<"EL PERIMETRO ES:" << perimetro(); cout<<"EL AREA ES:" << area(); };
Polimorfismo desde una interfaz
Aunque el polimorfismo es el mismo se aplique donde se aplique, el modo en que se aplica desde una interfaz puede resultar un poco más oscuro y difícil de entender. Se expone un sencillo ejemplo (en VB-NET) comentado para entender como funciona aplicado desde una interfaz, primero se escribe el código y luego se comenta el funcionamiento. Nota: para no enturbiar el código en exceso, todo lo que no se declara privado se sobreentiende público.
' Declaramos una interfaz llamada IOperar y declaramos una función llamada Operar ' que implementarán las clases deseadas: Interface IOperar Function Operar(valor1 as integer, valor2 as integer) as long End Interface
' Declaramos una clase que trabaja más alejada del usuario y que contendría funciones comunes ' para las siguiente clase, si no fueran idénticas irían en la interfaz, ' pero al caso de mostrar el polimorfismo se suponen idénticas: Class Operacion Function Calcular(clasellamante as Object) as Long ' aquí iría el código común a todas las operaciones.... que llaman a esa función ' por ejemplo recoger los 2 valores de la operación, chequear que están en el rango deseado, etc. ' se supone que la función inputValor recoge un valor de algún sitio valor1 as integer = inputValor() valor2 as integer = inputValor() op as New IOperar = clasellamante Return op.Operar(valor1,valor2) 'AQUÍ es donde se utiliza el polimorfismo. End Function End Class
' Declaramos 2 clases: Sumar y Resta que implementan la interfaz y que llaman a la clase Operacion: Class Sumar Implements IOperar Private Function Operar(valor1 as Integer, valor2 as Integer) as Long Implements IOperar.Operar Return valor1 + valor2 End Function Function Calcular() as Long op as New operacion Return op.Calcular(Me) ' se está llamando a la función 'Calcular' de la clase 'Operación' End Function End Class
' segunda clase.... Class Restar Implements IOperar Private Function Operar(valor1 as Integer, valor2 as Integer) as Long Implements IOperar.Operar Return valor1 - valor2 End Function Function Calcular() as Long op as New operacion Return op.Calcular(Me) ' se está llamando a la función 'Calcular' de la clase 'Operación' End Function End Class
Analicemos ahora el código para entender el polimorfismo expuesto en la interfaz: La interfaz expone un método que puede ser implementado por las diferentes clases, normalmente relacionadas entre si. Las clases Sumar y Restar implementan la interfaz pero el método de la interfaz lo declaramos privado para evitar ser accedido libremente y además tienen un método llamado Calcular que llama a la clase Operacion donde tenemos otro método con el mismo nombre. Es esta clase última la que realiza el polimorfismo y debe fijarse como es a través de una instancia de la interfaz que llama al método operar. La interfaz sabe a qué método de qué clase llamar desde el momento que asignamos un valor a la variable OP en el método Calcular de la clase Operacion, que a su vez recibió la referencia del método Calcular desde la clase que la llama, sea está cual sea se identifica a sí misma, mediante la referencia Me ó This según el lenguaje empleado. Debe notarse que la instancia de la interfaz accede a sus métodos aunque en sus clases se hayan declarado privadas.
Diferencias entre polimorfismo y sobrecarga
El polimorfismo como se muestra en el ejemplo anterior, suele ser bastante ventajoso aplicado desde las interfaces, ya que permite crear nuevos tipos sin necesidad de tocar las clases ya existentes (imaginemos que deseamos añadir una clase Multiplicar), basta con recompilar todo el código que incluye los nuevos tipos añadidos. Si se hubiera recurrido a la sobrecarga durante el diseño exigiría retocar la clase anteriormente creada al añadir la nueva operación Multiplicar, lo que además podría suponer revisar todo el código donde se instancia a la clase.
- La sobrecarga se da siempre dentro de una sola clase, mientras que el polimorfismo se da entre clases distintas.
- Un método está sobrecargado si dentro de una clase existen dos o más declaraciones de dicho método con el mismo nombre pero con parámetros distintos, por lo que no hay que confundirlo con polimorfismo.
- En definitiva: La sobrecarga se resuelve en tiempo de compilación utilizando los nombres de los métodos y los tipos de sus parámetros; el polimorfismo se resuelve en tiempo de ejecución del programa, esto es, mientras se ejecuta, en función de que clase pertenece un objeto.
Wikimedia foundation. 2010.