Composición en Python: crear relaciones entre objetos sin herencia
Clase 8 de 17 • Curso de Python Orientado a Objetos
Resumen
Aprende a dominar la composición en Python para construir sistemas robustos y flexibles en programación orientada a objetos. Aquí verás cómo combinar objetos existentes, cuándo preferir composición sobre herencia, y cómo implementar una clase Biblioteca que administra libros y usuarios con métodos claros y reutilizables. Con ejemplos prácticos como LibroProtocol, LibroFísico y LibroDigital, entenderás cómo modelar reglas reales sin complicar tu diseño.
¿Qué resuelve la composición en Python?
La composición permite combinar objetos dentro de otros para crear funcionalidades más grandes sin fabricar “cada ladrillo” desde cero. En vez de extender clases, integras instancias: una relación “tiene un” que resulta más flexible que la herencia en muchos casos.
- Usa objetos ya creados y reutiliza su comportamiento.
- Evita dependencias rígidas de jerarquías con herencia.
- Modela relaciones del dominio: la biblioteca “tiene” usuarios y libros.
¿Cuándo usar composición vs herencia?
La herencia modela “es un” (por ejemplo: el usuario es un profesor). La composición modela “tiene un” (por ejemplo: la Biblioteca tiene usuarios y tiene libros). Esta distinción guía un diseño más claro y mantenible.
¿Cómo se aplicó con libros físicos y digitales?
Se definió un LibroProtocol con los métodos prestar, devolver y calcular duración. Luego se implementaron dos clases: LibroFísico y LibroDigital, que difieren en el método calcular duración: el libro físico se presta 7 días y el digital 14 días. Así, la variación de comportamiento vive en cada clase concreta sin cambiar el contrato del protocolo.
¿Cómo implementar la clase biblioteca y su método de libros disponibles?
La clase Biblioteca encapsula datos y acciones del dominio. En su constructor se guarda un nombre y se inician dos listas vacías: libros y usuarios. Se instancia con el nombre “PlaziBiblioteca”. Luego se crean libros de ejemplo: “MiLibro”, “MiLibroNoDisponible” (marcado como no disponible) y “OtroLibro”; todos se asignan a la colección de la biblioteca.
- Constructor con nombre y listas vacías para libros y usuarios.
- La biblioteca centraliza el catálogo, por lo que el catálogo previo ya no es necesario.
- Se actualiza el estado de disponibilidad de un libro con un booleano.
¿Qué estructura tiene Biblioteca?
- Atributos: nombre, lista de libros, lista de usuarios.
- Control del estado: cada libro tiene un atributo disponible.
- Punto único de acceso a funcionalidades del dominio.
¿Cómo filtrar libros disponibles con un método?
Se implementa un método que retorna los títulos disponibles recorriendo la colección interna y filtrando por el atributo disponible. El uso de self y un for con if hace el código conciso y expresivo.
class Biblioteca:
def __init__(self, nombre):
self.nombre = nombre
self.libros = []
self.usuarios = []
def libros_disponibles(self):
return [libro.titulo for libro in self.libros if libro.disponible]
- Invocación del método desde el objeto Biblioteca con paréntesis.
- Se imprime el resultado con print y se ejecuta con: python main.py.
- Al cambiar disponible a True, el título aparece en la lista; si es False, se excluye.
¿Qué debes practicar a continuación?
- Diferenciar “es un” vs “tiene un” al modelar clases.
- Usar protocolos o interfaces para estandarizar métodos.
- Encapsular listas internas y exponer métodos útiles (por ejemplo, libros_disponibles).
- Mantener atributos simples y expresivos (como disponible en cada libro).
Como reto, piensa en otra composición útil dentro del sistema de bibliotecas (por ejemplo, relación entre préstamos y usuarios) y cuéntala en los comentarios: ¿qué objetos se combinan y qué métodos expondrías?