El polimorfismo permite escribir código flexible y reutilizable al permitirnos trabajar con objetos a un nivel más abstracto, sin necesidad de conocer sus tipos específicos.
Existen dos tipos principales de polimorfismo en la programación orientada a objetos:
Python admite principalmente el polimorfismo en tiempo de ejecución, ya que es un lenguaje de tipado dinámico. Sin embargo, podemos demostrar conceptos similares al polimorfismo en tiempo de compilación también.
Exploremos diferentes aspectos del polimorfismo en Python:
Python utiliza el duck typing, que es una forma de polimorfismo. La idea es: “Si camina como un pato y grazna como un pato, entonces debe ser un pato”. En otras palabras, Python se preocupa más por los métodos que tiene un objeto que por el tipo del objeto en sí.
class Pato:
def hablar(self):
return "¡Cuac cuac!"
class Perro:
def hablar(self):
return "¡Guau guau!"
class Gato:
def hablar(self):
return "¡Miau miau!"
def sonido_animal(animal):
return animal.hablar()
# Uso
pato = Pato()
perro = Perro()
gato = Gato()
print(sonido_animal(pato)) # Salida: ¡Cuac cuac!
print(sonido_animal(perro)) # Salida: ¡Guau guau!
print(sonido_animal(gato)) # Salida: ¡Miau miau!
En este ejemplo, sonido_animal() funciona con cualquier objeto que tenga un método hablar(), independientemente de su clase.
Sobrescribir métodos es un aspecto clave del polimorfismo en tiempo de ejecución. Ocurre cuando una clase derivada define un método con el mismo nombre que un método en su clase base.
class Figura:
def area(self):
pass
class Rectangulo(Figura):
def __init__(self, ancho, alto):
self.ancho = ancho
self.alto = alto
def area(self):
return self.ancho * self.alto
class Circulo(Figura):
def __init__(self, radio):
self.radio = radio
def area(self):
return 3.14159 * self.radio ** 2
# Uso
figuras = [Rectangulo(5, 4), Circulo(3)]
for figura in figuras:
print(f"Área: {figura.area()}")
# Salida:
# Área: 20
# Área: 28.27431
Aquí, Rectangulo y Circulo sobrescriben el método area() de la clase Figura.
Python permite la sobrecarga de operadores, que es una forma de polimorfismo en tiempo de compilación. Permite que el mismo operador tenga diferentes significados según los operandos.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, otro):
return Vector(self.x + otro.x, self.y + otro.y)
def __str__(self):
return f"Vector({self.x}, {self.y})"
# Uso
v1 = Vector(2, 3)
v2 = Vector(3, 4)
v3 = v1 + v2
print(v3) # Salida: Vector(5, 7)
Aquí, hemos sobrecargado el operador + para nuestra clase Vector.
El módulo abc de Python proporciona infraestructura para definir clases base abstractas, que son una forma poderosa de definir interfaces en Python.
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def hacer_sonido(self):
pass
class Perro(Animal):
def hacer_sonido(self):
return "¡Guau!"
class Gato(Animal):
def hacer_sonido(self):
return "¡Miau!"
# Uso
def sonido_animal(animal):
return animal.hacer_sonido()
perro = Perro()
gato = Gato()
print(sonido_animal(perro)) # Salida: ¡Guau!
print(sonido_animal(gato)) # Salida: ¡Miau!
# Esto generará un TypeError
# animal = Animal()
Las clases base abstractas no pueden utilizarse para crear objetos y obligan a las clases derivadas a implementar ciertos métodos, asegurando una interfaz consistente.
El polimorfismo se utiliza ampliamente en aplicaciones del mundo real:
Aquí hay un ejemplo simple de un sistema de plugins:
class Plugin(ABC):
@abstractmethod
def procesar(self, datos):
pass
class PluginMayusculas(Plugin):
def procesar(self, datos):
return datos.upper()
class PluginInvertir(Plugin):
def procesar(self, datos):
return datos[::-1]
class Aplicacion:
def __init__(self):
self.plugins = []
def agregar_plugin(self, plugin):
self.plugins.append(plugin)
def procesar_datos(self, datos):
for plugin in self.plugins:
datos = plugin.procesar(datos)
return datos
# Uso
app = Aplicacion()
app.agregar_plugin(PluginMayusculas())
app.agregar_plugin(PluginInvertir())
resultado = app.procesar_datos("Hola, Mundo!")
print(resultado) # Salida: !ODNUM ,ALOH
Este ejemplo demuestra cómo el polimorfismo permite que la clase Aplicacion trabaje con diferentes plugins a través de una interfaz común.
¡Gracias por llegar hasta acá! Espero que este recorrido por el universo de la programación haya sido tan apasionante para vos como lo fue para mí escribirlo.
Nos encantaría escuchar lo que pensás, así que no te quedes callado/a, dejá tus comentarios, sugerencias y todas esas ideas copadas que seguro se te ocurrieron.
Y para ir más allá de estas líneas, date una vuelta por los ejemplos prácticos que preparamos para vos. Vas a encontrar todo el código y los proyectos en nuestro repositorio de GitHub learn-software-engineering/examples.
¡Gracias por ser parte de esta comunidad de aprendizaje. Seguí programando y explorando nuevos territorios en este fascinante mundo de la computación!