El polimorfismo es uno de los pilares fundamentales de la programación orientada a objetos (junto a la encapsulación, la herencia y la abstracción). La palabra proviene del griego poly (muchos) y morphé (forma), y se refiere a la capacidad que tienen los objetos de diferentes clases para responder al mismo mensaje (método), cada uno de una manera distinta.
En otras palabras, el polimorfismo permite que un mismo método pueda ser ejecutado de forma diferente según el objeto que lo invoque. Esta característica promueve la flexibilidad y la extensibilidad del código, ya que se pueden definir funciones o métodos que operen con diferentes tipos de objetos sin preocuparse por su clase concreta.
Ejemplo conceptual:
Imaginemos una función hacer_sonido()
que recibe un animal cualquiera. En lugar de preocuparnos si es un perro, un gato o un loro, simplemente invocamos su método hablar()
, y cada objeto responderá de manera acorde a su propia implementación.
Tipos de polimorfismo:
Existen varios tipos de polimorfismo. A continuación, te presentamos los más relevantes:
1. Polimorfismo ad hoc:
- También conocido como sobrecarga de métodos o funciones.
- No se aplica directamente en Python, ya que no permite sobrecarga de funciones en el sentido clásico.
- Se puede emular mediante argumentos opcionales o valores por defecto.
2. Polimorfismo paramétrico:
- Consiste en escribir funciones o clases genéricas que funcionen con distintos tipos de datos.
- En Python, se puede lograr usando tipos genéricos con el módulo typing.
3. Polimorfismo de inclusión (por herencia):
- Es el tipo más común.
- Permite que una clase hija pueda ser tratada como una clase padre, y aún así comportarse de forma específica.
Ventajas del polimorfismo:
- Flexibilidad: Puedes escribir funciones o métodos que operen con distintos tipos de objetos sin cambiar el código.
- Extensibilidad: Agregar nuevas clases o tipos no requiere modificar el código que usa polimorfismo.
- Reutilización: Se promueve el uso de funciones genéricas y estructuras más limpias
Polimorfismo en lenguajes con tipado estático:
En lenguajes como Java o C++, que utilizan tipado estático, el polimorfismo se logra principalmente a través de interfaces o clases abstractas. Estos lenguajes requieren que las clases compartan una jerarquía común (por herencia) y que implementen métodos definidos en un contrato común (interfaz o clase base).
Aunque Python no obliga a esto por ser un lenguaje de tipado dinámico, entender este enfoque puede ayudarte a comprender mejor la filosofía detrás del polimorfismo.
Polimorfismo en Python:
Python implementa el polimorfismo de forma más flexible gracias a su tipado dinámico. A diferencia de los lenguajes con tipado estático, en Python no es necesario que las clases hereden de una clase común ni que implementen una interfaz específica. Basta con que los objetos tengan los métodos requeridos. Esta característica es conocida como duck typing (que explicaremos en un capítulo posterior).
Ejemplo:
Supongamos que tenemos una clase base Animal
y dos subclases Perro
y Gato
. Cada subclase implementa su propia versión del método hablar()
:
class Animal:
def hablar(self):
pass # Método abstracto (opcional en Python)
class Perro(Animal):
def hablar(self):
return "¡Guau!"
class Gato(Animal):
def hablar(self):
return "¡Miau!"
Ahora podemos crear objetos de cada clase y tratarlos de forma polimórfica:
animales = [Perro(), Gato()]
for animal in animales:
print(animal.hablar())
Como puedes ver, el mismo método hablar()
se comporta de manera distinta según el tipo de objeto, aunque los tratamos a todos como instancias de una clase genérica.
Polimorfismo sin herencia: duck typing
En Python, incluso sin herencia, el polimorfismo puede funcionar si los objetos tienen métodos con el mismo nombre. Veamos otro ejemplo:
class Pato:
def hablar(self):
return "Cuac"
class Persona:
def hablar(self):
return "Hola"
def saludar(objeto):
print(objeto.hablar())
saludar(Pato()) # Cuac
saludar(Persona()) # Hola
Aquí, saludar()
no necesita saber qué clase tiene el objeto. Solo asume que el objeto tiene un método hablar()
. Este comportamiento es una manifestación del principio "Si camina como un pato y suena como un pato, probablemente sea un pato", que da nombre al duck typing.