El polimorfismo es uno de los pilares fundamentales de la Programación Orientada a Objetos (POO). En términos simples, el polimorfismo permite que una misma operación o método se comporte de diferentes maneras en diferentes contextos. Esto se logra a través de la herencia y la sobreescritura de métodos en las clases derivadas.
Conceptos Clave
- Polimorfismo en Tiempo de Compilación: También conocido como polimorfismo estático, se logra mediante la sobrecarga de métodos y operadores.
- Polimorfismo en Tiempo de Ejecución: También conocido como polimorfismo dinámico, se logra mediante la herencia y la sobreescritura de métodos.
Polimorfismo en Tiempo de Ejecución
En Python, el polimorfismo en tiempo de ejecución se logra principalmente a través de la herencia y la sobreescritura de métodos. Vamos a explorar esto con un ejemplo práctico.
Ejemplo Práctico
Supongamos que tenemos una clase base Animal y dos clases derivadas Perro y Gato. Ambas clases derivadas sobrescriben el método hacer_sonido de la clase base.
class Animal:
def hacer_sonido(self):
raise NotImplementedError("Este método debe ser sobrescrito por las subclases")
class Perro(Animal):
def hacer_sonido(self):
return "Guau"
class Gato(Animal):
def hacer_sonido(self):
return "Miau"
# Uso del polimorfismo
animales = [Perro(), Gato()]
for animal in animales:
print(animal.hacer_sonido())Explicación del Código
-
Clase Base
Animal:- Define un método
hacer_sonidoque lanza una excepciónNotImplementedError. Esto indica que las subclases deben sobrescribir este método.
- Define un método
-
Clase Derivada
Perro:- Sobrescribe el método
hacer_sonidopara devolver "Guau".
- Sobrescribe el método
-
Clase Derivada
Gato:- Sobrescribe el método
hacer_sonidopara devolver "Miau".
- Sobrescribe el método
-
Uso del Polimorfismo:
- Creamos una lista de objetos
animalesque contiene instancias dePerroyGato. - Iteramos sobre la lista y llamamos al método
hacer_sonidoen cada objeto. Gracias al polimorfismo, el método correcto se llama en función del tipo de objeto.
- Creamos una lista de objetos
Ejercicio Práctico
Vamos a reforzar el concepto con un ejercicio práctico.
Ejercicio
Crea una clase base Vehiculo con un método moverse. Luego, crea dos clases derivadas Coche y Bicicleta que sobrescriban el método moverse. Finalmente, crea una lista de objetos de tipo Vehiculo y llama al método moverse en cada uno.
Solución
class Vehiculo:
def moverse(self):
raise NotImplementedError("Este método debe ser sobrescrito por las subclases")
class Coche(Vehiculo):
def moverse(self):
return "El coche se está moviendo"
class Bicicleta(Vehiculo):
def moverse(self):
return "La bicicleta se está moviendo"
# Uso del polimorfismo
vehiculos = [Coche(), Bicicleta()]
for vehiculo in vehiculos:
print(vehiculo.moverse())Retroalimentación y Consejos
- Error Común: Olvidar sobrescribir el método en las subclases. Esto resultará en una excepción
NotImplementedError. - Consejo: Siempre asegúrate de que las subclases sobrescriban los métodos de la clase base cuando sea necesario.
- Buena Práctica: Utiliza el polimorfismo para escribir código más flexible y mantenible. Esto permite que tu código trabaje con objetos de diferentes clases de manera uniforme.
Conclusión
El polimorfismo es una herramienta poderosa en la Programación Orientada a Objetos que permite que una misma operación se comporte de diferentes maneras según el contexto. En Python, esto se logra principalmente a través de la herencia y la sobreescritura de métodos. Al dominar el polimorfismo, puedes escribir código más flexible y reutilizable, lo que facilita el mantenimiento y la extensión de tus programas.
En el próximo tema, exploraremos la Encapsulación, otro pilar fundamental de la POO, que te permitirá controlar el acceso a los datos y métodos dentro de tus clases.
Curso de Programación en Python
Módulo 1: Introducción a Python
- Introducción a Python
- Configuración del Entorno de Desarrollo
- Sintaxis de Python y Tipos de Datos Básicos
- Variables y Constantes
- Entrada y Salida Básica
Módulo 2: Estructuras de Control
- Sentencias Condicionales
- Bucles: for y while
- Herramientas de Control de Flujo
- Comprensiones de Listas
Módulo 3: Funciones y Módulos
- Definición de Funciones
- Argumentos de Función
- Funciones Lambda
- Módulos y Paquetes
- Visión General de la Biblioteca Estándar
Módulo 4: Estructuras de Datos
Módulo 5: Programación Orientada a Objetos
Módulo 6: Manejo de Archivos
- Lectura y Escritura de Archivos
- Trabajo con Archivos CSV
- Manejo de Datos JSON
- Operaciones de Archivos y Directorios
Módulo 7: Manejo de Errores y Excepciones
- Introducción a las Excepciones
- Manejo de Excepciones
- Lanzamiento de Excepciones
- Excepciones Personalizadas
Módulo 8: Temas Avanzados
- Decoradores
- Generadores
- Administradores de Contexto
- Concurrencia: Hilos y Procesos
- Asyncio para Programación Asíncrona
Módulo 9: Pruebas y Depuración
- Introducción a las Pruebas
- Pruebas Unitarias con unittest
- Desarrollo Guiado por Pruebas
- Técnicas de Depuración
- Uso de pdb para Depuración
Módulo 10: Desarrollo Web con Python
- Introducción al Desarrollo Web
- Fundamentos del Framework Flask
- Construcción de APIs REST con Flask
- Introducción a Django
- Construcción de Aplicaciones Web con Django
Módulo 11: Ciencia de Datos con Python
- Introducción a la Ciencia de Datos
- NumPy para Computación Numérica
- Pandas para Manipulación de Datos
- Matplotlib para Visualización de Datos
- Introducción al Aprendizaje Automático con scikit-learn
