Contenido del curso
El software y la ingeniería
Diseño de software
Patrones de diseño
POO
Conclusiones finales
Relaciones entre clases en UML
Resumen
Entender las relaciones entre clases en UML es la base para diseñar código orientado a objetos que sea claro, mantenible y escalable. Aquí descubrirás cómo se conectan las clases mediante dependencia, asociación, implementación, herencia, agregación y composición, con ejemplos prácticos pensados para quienes ya programan y quieren modelar mejor sus sistemas.
¿Qué es UML y cómo se lee un diagrama de clases?
UML, o Unified Modeling Language, es un lenguaje unificado de modelado que describe de forma gráfica diagramas de clases y de procesos [0:25]. Su especificación incluye una cantidad importante de elementos para representar cómo se construyen sistemas en lenguajes orientados a objetos.
En un diagrama de clases típico, como el de la clase persona, encuentras tres bloques: el nombre arriba, las propiedades que representan el estado interno de cada instancia, y los métodos que definen su comportamiento, por ejemplo correr, caminar o hacer un sprint [1:10].
¿Qué representa el símbolo menos y el símbolo más en UML? El menos indica visibilidad privada y el más indica visibilidad pública. Lo privado solo se accede dentro de la clase; lo público forma la interfaz expuesta al resto del sistema [1:55].
¿Qué son los métodos estáticos en una clase?
Los métodos estáticos se representan con una línea subrayada en el diagrama y no requieren crear una instancia para usarse [2:30]. Se conocen como elementos de clase, no de instancia, y se invocan directamente con el nombre de la clase, por ejemplo Person.race. Sirven para guardar información o comportamiento común a todas las instancias.
¿Cómo se diferencian dependencia y asociación entre clases?
La relación de dependencia existe cuando un cambio en una clase obliga a modificar otra [3:25]. Es la más general: siempre que dos clases se conectan, hay algún nivel de dependencia.
Piensa en una clase Builder con un método build que recibe un hammer de tipo Tool como parámetro. Si la interfaz pública de Tool cambia, por ejemplo el método useIt pasa a llamarse useTool, tendrás que modificar Builder [4:00].
La relación de asociación ocurre cuando una clase tiene acceso permanente a objetos de otra, normalmente como atributo [4:45]. En la misma clase Builder, ahora declaras una propiedad ownHammer de tipo Tool. Esa instancia vive con el objeto y la usas en cualquier método sin pasarla como parámetro cada vez.
¿Cuál es la diferencia entre dependencia y asociación? En dependencia el objeto se pasa como parámetro puntual; en asociación el objeto se guarda como atributo y persiste en la instancia.
¿Qué es la relación de implementación y cómo aparece la herencia?
La relación de implementación se da cuando una clase define su comportamiento con base en una interfaz [5:40]. Una interfaz es un contrato: quien quiera ser ese tipo, debe implementar todos sus métodos.
Imagina la interfaz TextFormatter con el método format(text). Las clases PlanTextFormatter y ShortTextFormatter la implementan, pero cada una resuelve format a su manera. Eso es polimorfismo en acción [6:15].
¿Cómo funciona la herencia entre clases?
Hay herencia cuando una clase usa la misma interfaz e implementación de otra y además puede extender su comportamiento [6:50]. Tomemos la clase Node con atributos text y next, usada por LinkedList que expone append y remove.
Si creas QueueLinkedList que hereda de LinkedList, los métodos append y remove siguen disponibles a través de parent, y encima puedes añadir enqueue y dequeue para modelar una cola [7:30]. Reutilizas el comportamiento existente y agregas el que necesitas.
¿Cuándo usar agregación y cuándo composición?
La relación de agregación ocurre cuando un objeto tiene uno o más objetos de otra clase, pero no gestiona su ciclo de vida [8:40]. En una clase Vehicle con atributos engine de tipo Engine y wheels como lista de Wheel, el constructor recibe el motor y las llantas ya creados. Le agregas piezas que existían antes.
La relación de composición sucede cuando el objeto consiste de uno o más objetos de otra clase y sí gestiona su ciclo de vida [9:30]. En la misma clase Vehicle, el constructor crea internamente el motor y la lista de llantas con algo como Wheel.get. Si destruyes el vehículo, esos componentes desaparecen con él.
¿Cuándo elegir composición sobre agregación? Si el objeto contenido no tiene sentido fuera del contenedor, usa composición. Si puede vivir y reutilizarse en otros contextos, usa agregación.
La decisión depende del modelaje de tu aplicación. Pregúntate si el motor puede vivir fuera del vehículo, si las instancias se reutilizan en otros coches, y si el ciclo de vida de uno depende del otro. Estas relaciones, aunque nacen en programación orientada a objetos, son aplicables a cualquier paradigma con un cambio de enfoque.
¿Habías trabajado con UML antes? ¿Qué relaciones usas más al diseñar tu código? Cuéntanos en los comentarios.