Polimorfismo

El polimorfismo es un concepto fundamental de la programación orientada a objetos (POO) que permite tratar diferentes objetos de una jerarquía de clases de manera uniforme. Permite que un objeto pueda manifestar múltiples formas o comportamientos.

El polimorfismo se basa en la idea de que una clase base puede definir una interfaz común para todas las clases derivadas, y que estas clases derivadas pueden proporcionar implementaciones específicas de esa interfaz. Esto significa que, aunque los objetos pueden ser de tipos diferentes, pueden ser tratados de manera genérica a través de un puntero o referencia a la clase base.

El polimorfismo se logra a través de dos mecanismos principales:

1.- Polimorfismo de tiempo de compilación (o estático).- Se logra mediante el uso de funciones virtuales y la herencia de clases. Cuando una función es declarada como virtual en la clase base, puede ser sobrescrita por las clases derivadas. Esto permite que la llamada a una función virtual se resuelva en tiempo de ejecución, utilizando la implementación adecuada según el tipo real del objeto.

2.- Polimorfismo de tiempo de ejecución (o dinámico).- Se logra utilizando punteros o referencias a la clase base para acceder a los objetos de las clases derivadas. Mediante el uso de la palabra clave virtual en la declaración de funciones en la clase base y el operador de resolución de alcance (-> o .), se puede acceder a las funciones virtuales de las clases derivadas a través del puntero o referencia a la clase base. Esto permite que el comportamiento de la función se determine en tiempo de ejecución según el tipo real del objeto apuntado o referenciado.

El polimorfismo en C++ facilita la escritura de código más flexible, extensible y reutilizable, ya que permite tratar objetos de diferentes tipos de manera uniforme, aprovechando la herencia y la capacidad de sustituir objetos de clases derivadas por objetos de la clase base. Esto se logra mediante el uso de funciones virtuales y la capacidad de sobrescribirlas en las clases derivadas. Al utilizar polimorfismo, el código puede adaptarse dinámicamente a los diferentes tipos de objetos en tiempo de ejecución, promoviendo así un diseño más modular y mantenible. Además, el polimorfismo juega un papel crucial en la implementación de interfaces comunes a través de clases base abstractas, lo que fomenta la coherencia y la consistencia en la estructura del programa. En resumen, el polimorfismo en C++ es una herramienta poderosa que contribuye a la creación de software robusto y escalable.

Ejemplo de Polimorfismo de tiempo de compilación (o estático)

En este ejemplo, tenemos una clase base llamada Animal que define una función virtual hacerSonido().

Luego, creamos dos clases derivadas, Perro y Gato, que sobrescriben la función hacerSonido() con sus propias implementaciones.

En la función main(), creamos dos punteros Animal* que apuntan a objetos Perro y Gato, respectivamente.

Luego, llamamos a la función hacerSonido() en ambos punteros. Aunque los punteros son de tipo Animal*, el comportamiento de la función se resuelve en tiempo de ejecución según el tipo real de los objetos apuntados.

El resultado de la ejecución será:

Ejemplo de Polimorfismo de tiempo de ejecución (o dinámico)

En este ejemplo, tenemos las mismas clases Animal, Perro y Gato que en el ejemplo anterior.

En la función main(), creamos objetos Perro y Gato.

Luego, creamos dos referencias Animal& que hacen referencia a los objetos Perro y Gato, respectivamente.

A través de estas referencias, llamamos a la función hacerSonido(). Aunque las referencias son de tipo Animal&, el comportamiento de la función se determina en tiempo de ejecución según el tipo real de los objetos referenciados.

El resultado de la ejecución será el mismo que en el ejemplo anterior:

Reglas para aplicar polimorfismo de tiempo de compilación

El polimorfismo de tiempo de compilación, también conocido como polimorfismo estático, se basa en el uso de funciones virtuales y la herencia de clases en C++. Aquí están las reglas básicas para aplicar el polimorfismo de tiempo de compilación:

Definir una función virtual en la clase base.- Debes declarar una función en la clase base con la palabra clave virtual. Esto indica que la función es potencialmente sobrescribible por las clases derivadas.

Sobrescribir la función en las clases derivadas.- En las clases derivadas, debes declarar una función con la misma firma que la función virtual de la clase base y utilizar la palabra clave override. Esto indica que estás sobrescribiendo la función virtual de la clase base.

Utilizar punteros o referencias a la clase base.- Para lograr el polimorfismo, debes utilizar punteros o referencias a la clase base para apuntar a objetos de las clases derivadas. Esto permite tratar los objetos de diferentes tipos de manera uniforme.

Llamar a la función virtual.- A través del puntero o referencia a la clase base, puedes llamar a la función virtual. En tiempo de ejecución, se utilizará la implementación adecuada según el tipo real del objeto apuntado o referenciado.

El polimorfismo de tiempo de ejecución te permite tratar objetos de diferentes tipos de manera uniforme y utilizar la implementación adecuada en tiempo de ejecución. Esto es especialmente útil cuando se trabaja con jerarquías de clases y se desea tener comportamientos diferentes para cada tipo de objeto.