8. Relaciones en diagramas de clases: asociación, agregación, composición, dependencia y herencia

8.1 Introducción

En un diagrama de clases, las clases aisladas dicen poco. El valor del modelo aparece cuando se muestran las relaciones entre ellas: qué conceptos se conocen, cuáles dependen de otros, cuáles forman parte de un todo y cuáles especializan una idea más general.

UML ofrece varias relaciones para expresar distintos significados. Las más importantes en diagramas de clases son asociación, agregación, composición, dependencia y herencia, también llamada generalización. Usarlas correctamente permite construir modelos más precisos y fáciles de interpretar.

8.2 Por qué importan las relaciones

Una relación indica que dos clases no son independientes. Puede significar que una clase conoce a otra, la usa temporalmente, contiene objetos de otra, depende de ella para realizar una operación o representa una variante especializada.

Si se dibujan relaciones sin precisión, el diagrama se vuelve engañoso. Una línea mal elegida puede sugerir una dependencia fuerte donde solo hay un uso ocasional, o puede ocultar que una parte no tiene sentido sin el todo que la contiene.

Una relación UML no es solo una línea: expresa una decisión sobre cómo se conectan los conceptos o elementos de diseño.

8.3 Relaciones principales en diagramas de clases

Las relaciones más habituales permiten expresar distintos grados de vínculo entre clases. La asociación muestra un enlace estructural. La agregación y la composición representan relaciones todo-parte. La dependencia indica uso o necesidad puntual. La herencia expresa especialización entre una clase general y clases más específicas.

Relaciones en diagramas de clases UML: asociación, agregación, composición, dependencia y herencia

8.4 Asociación

La asociación representa un vínculo estructural entre clases. Indica que los objetos de una clase pueden estar conectados con objetos de otra. Por ejemplo, un Cliente puede tener Pedidos, o un Profesional puede atender Turnos.

Una asociación se representa con una línea continua. Puede incluir nombres de roles, multiplicidades y navegabilidad, aunque esos detalles se estudiarán con mayor profundidad en el próximo tema.

8.5 Asociación bidireccional y unidireccional

Una asociación puede ser bidireccional cuando ambos extremos conocen el vínculo, o unidireccional cuando solo un lado necesita navegar hacia el otro. En UML, la navegabilidad puede indicarse con una flecha.

Por ejemplo, un Pedido puede necesitar conocer al Cliente que lo realizó, pero tal vez el modelo no requiera que Cliente mantenga una colección directa de todos sus pedidos. La decisión depende de lo que se necesita representar, no de una regla fija.

8.6 Agregación

La agregación representa una relación todo-parte débil. El todo agrupa partes, pero las partes pueden existir independientemente. Se dibuja con un rombo blanco en el extremo del todo.

Por ejemplo, una Universidad puede agrupar Departamentos, pero un Departamento podría reorganizarse, trasladarse o existir dentro de otra estructura. La agregación indica pertenencia, aunque no una dependencia fuerte de ciclo de vida.

8.7 Composición

La composición representa una relación todo-parte fuerte. La parte pertenece al todo de manera más estricta y normalmente no tiene sentido independiente fuera de él. Se dibuja con un rombo negro en el extremo del todo.

Por ejemplo, una Factura puede estar compuesta por DetallesDeFactura. Si se elimina la factura, sus detalles pierden sentido. La composición expresa una dependencia fuerte de pertenencia y ciclo de vida.

8.8 Diferencia entre agregación y composición

La diferencia principal está en la fuerza de la relación. En la agregación, la parte puede existir por separado. En la composición, la parte depende fuertemente del todo. Esta diferencia debe analizarse según el dominio y el propósito del modelo.

Relación Significado Ejemplo
Agregación Todo-parte débil; la parte puede existir independientemente. Equipo y Jugador, Biblioteca y Libro.
Composición Todo-parte fuerte; la parte depende del todo. Factura y DetalleDeFactura, Pedido y LíneaDePedido.

8.9 Dependencia

La dependencia indica que una clase usa o necesita a otra, pero sin mantener necesariamente una relación estructural permanente. Se representa con una línea discontinua y una flecha hacia la clase de la cual se depende.

Por ejemplo, un ServicioDeTurnos puede depender de un ServicioDeNotificaciones para enviar un aviso después de confirmar una reserva. Si cambia la interfaz del servicio de notificaciones, el servicio de turnos puede verse afectado.

8.10 Asociación frente a dependencia

La asociación suele indicar una relación más estable entre objetos. La dependencia suele indicar un uso más puntual o una necesidad para realizar una operación. Elegir entre ambas requiere pensar qué se quiere comunicar.

Si una clase conserva una referencia a otra como parte de su estado, puede corresponder una asociación. Si solo la usa como parámetro, variable local o servicio temporal, puede corresponder una dependencia.

8.11 Herencia o generalización

La herencia, en UML llamada generalización, expresa una relación entre una clase general y una clase más específica. Se representa con una línea continua y un triángulo vacío apuntando hacia la clase general.

Por ejemplo, TarjetaDeCrédito y TransferenciaBancaria pueden especializar MedioDePago. Esto significa que comparten una abstracción común, pero cada una puede tener datos o comportamientos propios.

8.12 Cuándo usar herencia

La herencia debe usarse cuando existe una relación clara de tipo "es un". Un Administrador es un Usuario. Un PagoConTarjeta es un MedioDePago. Un Médico es un Profesional. Si la frase no tiene sentido, probablemente no corresponde usar herencia.

No conviene usar herencia solo para reutilizar código o porque dos clases se parecen. La herencia crea una relación fuerte. Si se usa mal, puede volver rígido el diseño.

8.13 Clase abstracta

Una clase abstracta representa una idea general que no se instancia directamente. Sirve como base para clases más específicas. En UML puede indicarse con el nombre en cursiva o con una marca como {abstract}.

Por ejemplo, MedioDePago puede ser abstracta si en el sistema siempre se trabaja con formas concretas como TarjetaDeCrédito, TransferenciaBancaria o BilleteraVirtual.

8.14 Interfaz y realización

Una interfaz define operaciones que otras clases deben ofrecer. La relación de realización indica que una clase cumple una interfaz. En UML suele representarse con una línea discontinua y un triángulo vacío apuntando hacia la interfaz.

Por ejemplo, una interfaz Notificador puede definir enviarMensaje(). Luego NotificadorEmail y NotificadorSMS pueden realizar esa interfaz con implementaciones distintas.

8.15 Relaciones y nivel de abstracción

Las relaciones deben ser coherentes con el nivel del diagrama. En un modelo conceptual, una asociación puede expresar que Cliente realiza Pedido. En un modelo de diseño, tal vez aparezcan dependencias entre servicios, repositorios e interfaces.

Mezclar relaciones conceptuales con dependencias técnicas puede generar confusión. Antes de dibujar relaciones, conviene aclarar si el diagrama representa el dominio del problema, una solución de diseño o una vista cercana al código.

8.16 Ejemplo: sistema de ventas

En un sistema de ventas, Cliente puede estar asociado con Pedido. Pedido puede estar compuesto por LíneaDePedido, porque una línea no tiene sentido sin su pedido. Producto puede asociarse con LíneaDePedido, porque cada línea se refiere a un producto. PagoConTarjeta puede heredar de MedioDePago. ServicioDePedidos puede depender de ServicioDePagos para confirmar el cobro.

Estas relaciones no son intercambiables. Cada una comunica un tipo de vínculo diferente y ayuda a entender la estructura del sistema.

8.17 Criterios para elegir una relación

  • Si dos clases mantienen un vínculo estructural, considera una asociación.
  • Si una clase solo usa a otra para una operación, considera una dependencia.
  • Si existe una relación todo-parte débil, considera una agregación.
  • Si la parte depende fuertemente del todo, considera una composición.
  • Si una clase específica es un tipo de otra más general, considera herencia.
  • Si una clase cumple un contrato definido por una interfaz, considera realización.

8.18 Errores frecuentes

  • Usar asociación para cualquier relación sin analizar su significado.
  • Confundir agregación y composición.
  • Usar composición cuando la parte puede existir sin el todo.
  • Usar herencia solo porque dos clases tienen atributos parecidos.
  • Representar dependencias técnicas en un diagrama conceptual sin aclaración.
  • Dibujar demasiadas relaciones y volver ilegible el diagrama.
  • Olvidar que una relación debe comunicar una decisión del modelo.

8.19 Qué debes recordar de este tema

  • Las relaciones dan sentido al diagrama de clases.
  • La asociación representa un vínculo estructural.
  • La agregación y la composición representan relaciones todo-parte con distinta fuerza.
  • La dependencia indica uso o necesidad de una clase respecto de otra.
  • La herencia expresa especialización entre una clase general y una clase específica.
  • La relación elegida debe coincidir con el significado que se quiere comunicar.

8.20 Conclusión

Las relaciones en diagramas de clases permiten representar cómo se conectan las partes del modelo. Elegir correctamente entre asociación, agregación, composición, dependencia y herencia mejora la precisión del diseño y evita interpretaciones incorrectas.

En el próximo tema profundizaremos en multiplicidad, navegabilidad, roles y restricciones en diagramas de clases.