Programación Avanzada 2.º BT TI · DGETP / UTU
Profe MacónPROGRAMACIÓN AVANZADA
2.º BT TI · DGETP/UTU · 2026
CET1 · POO en Java
UNIDAD 01 · INTRODUCCIÓN A LA POO · LECCIÓN 03

Relaciones entre objetos y herencia

En «La Viñeta», comprender cómo colaboran Cliente, Venta, Producto y DetalleVenta nos permite diseñar relaciones correctas. Luego veremos qué cambia cuando una clase es una especialización de otra.

AsociacionesAgregaciónComposiciónHerenciaCET1
01 · El punto de partida

Volvemos al modelo de la tienda

En los dos SCORM anteriores aprendimos a identificar entidades, definir atributos y distribuir responsabilidades. Ahora necesitamos precisar qué significa cada línea que une nuestras clases.

UML conceptual de Cliente, Venta, Producto y clase de asociación DetalleVenta
Diagrama conceptual aportado: representa la venta y su detalle como clase de asociación.
UML de diseño con Cliente, Venta, Producto, DetalleVenta y atributos
Diagrama de diseño aportado: muestra atributos y relaciones cercanas a la implementación.
Observación importante: en nuestros dibujos aparecen rombos y una clase de asociación. No debemos interpretar automáticamente un rombo como prueba de que existe composición. La semántica de agregación o composición se justifica con reglas de pertenencia y ciclo de vida; el material original se conserva sin alterar.

La pregunta que orienta esta lección es: ¿un objeto simplemente conoce a otro, lo agrupa o es responsable de su existencia?

02 · Relación general

Asociación: un objeto conoce a otro

Una asociación representa un vínculo entre objetos. No afirma necesariamente quién los crea, quién es su propietario o cuánto tiempo viven.

Cliente
realiza →
asociación
Venta

En la tienda una venta corresponde a un cliente. En una implementación Java podemos representarlo con un atributo que guarde una referencia a un objeto de la clase Cliente.

Venta.java — referencia a otra clase
public class Venta {
    private int numero;
    private Cliente cliente;

    public Venta(int numero, Cliente cliente) {
        this.numero = numero;
        this.cliente = cliente;
    }
}
Pregunta conceptual: si se elimina el registro de una venta, ¿debe desaparecer el cliente del sistema? No. Esa independencia ayuda a entender por qué esta relación es una asociación, no una composición.

Multiplicidad: ¿cuántos objetos participan?

En un sistema real debemos determinar, por ejemplo, si un cliente puede realizar muchas ventas y si cada venta corresponde a un único cliente. En UML esto suele expresarse con 1, 0..1 o 0..*.

Los diagramas proporcionados no explicitan todas las multiplicidades, por lo que las siguientes afirmaciones se toman como supuestos didácticos del caso, no como datos ya escritos en el UML.

03 · Relación todo–parte débil

Agregación: agrupar sin depender para existir

La agregación compartida es una asociación todo–parte: el «todo» reúne elementos que pueden existir independientemente de él. En UML se representa con un rombo blanco junto al todo.

Catálogo
◇────
agrupa
Producto
Ejemplo propuesto para ampliar «La Viñeta»

Un Catalogo puede agrupar productos, pero eliminar ese catálogo no tendría por qué eliminar cada producto del inventario. Es un ejemplo pedagógico nuevo, no una clase presente en los UML originales.

Catalogo.java — ejemplo de agrupación
import java.util.List;

public class Catalogo {
    private String nombre;
    private List<Producto> productos;

    public Catalogo(String nombre, List<Producto> productos) {
        this.nombre = nombre;
        this.productos = productos;
    }
}

El atributo List<Producto> anticipa la siguiente lección, pero aquí lo importante no es su funcionamiento, sino qué significa la relación. Una lista por sí sola no demuestra que exista agregación.

Precisión UML: los modelos contemporáneos utilizan la agregación compartida con cautela porque su significado formal es menos fuerte que el de composición. Cuando no agrega información útil, una asociación simple suele ser suficiente.
04 · Relación todo–parte fuerte

Composición: partes que pertenecen a un todo

Una composición es una relación todo–parte fuerte. Cada parte pertenece como máximo a un todo compuesto a la vez, y el todo es responsable de su ciclo de vida dentro del modelo.

Venta
◆────
contiene
DetalleVenta

Para «La Viñeta», podemos decidir que cada detalle es un renglón de una venta concreta: no debe pertenecer simultáneamente a otra venta. Si eliminamos definitivamente una venta, sus detalles dejan de tener sentido en este modelo.

Venta.java — diseño posible con composición
import java.util.ArrayList;
import java.util.List;

public class Venta {
    private List<DetalleVenta> detalles;

    public Venta() {
        detalles = new ArrayList<>();
    }

    public void agregarProducto(Producto producto,
                                int cantidad,
                                double precioUnitario) {
        DetalleVenta detalle =
                new DetalleVenta(producto, cantidad, precioUnitario);
        detalles.add(detalle);
    }
}

En este diseño Venta crea el DetalleVenta. Esa decisión ayuda a expresar el control del todo sobre la parte, aunque composición no significa simplemente «usar new dentro de la clase». La regla sobre propiedad y vida de las partes es lo fundamental.

Ciclo de vida en el modelo elegido:
Venta creada → agrega detalles → conserva detalles → venta eliminada definitivamente → sus detalles dejan de pertenecer al modelo.
¿Y Producto? El producto del catálogo puede aparecer en muchas ventas diferentes; no debería desaparecer cuando se elimina un DetalleVenta. El detalle se asocia al producto, pero no lo posee mediante composición.
05 · Comparar sin confundir

Tres relaciones, tres preguntas diferentes

Asociación

¿Se conocen?

Cliente ↔ Venta

No impone una relación de ciclo de vida.

UML: línea simple.

Agregación

¿Uno agrupa a otros independientes?

Catálogo ◇— Producto

La parte puede existir fuera del conjunto.

UML: rombo blanco.

Composición

¿La parte pertenece fuertemente a un todo?

Venta ◆— DetalleVenta

La parte depende del ciclo de vida del todo definido por el modelo.

UML: rombo negro.

PreguntaAsociaciónAgregaciónComposición
¿Expresa todo–parte?No necesariamenteSíSí
¿Puede la parte tener vida independiente?La relación no lo defineSíDepende del todo en el modelo
¿Símbolo UML?Línea◇◆
Evita este error: declarar un atributo, una referencia o una ArrayList no convierte automáticamente la relación en agregación o composición. Primero razonamos sobre el problema; después elegimos cómo programarlo.
06 · Una relación diferente

Herencia: cuando el modelo necesita evolucionar

Las asociaciones describen vínculos entre objetos. La herencia expresa que un tipo de objeto es un tipo más específico de otro. Pero no empezamos dibujando flechas: primero aparece un problema de diseño.

El nuevo requerimiento de La Viñeta: además de registrar clientes, ahora necesitamos registrar a los vendedores y saber quién atendió cada venta. Vamos a revisar nuestro modelo tres veces, justificando cada cambio.

Primer intento · Sin herencia: repetimos información

Agregamos una clase Vendedor y la relacionamos con Venta. Funciona, pero Cliente y Vendedor repiten cedula, nombre y correo. Si cambiamos cómo representamos esos datos, tendremos que revisar ambas clases.

Primer modelo UML: Cliente y Vendedor son clases independientes. Ambas repiten cédula, nombre y correo; Vendedor también tiene teléfono. Cada una se relaciona con Venta.
Modelo 1 · Sin herencia. Agregamos al vendedor, pero aparecen atributos duplicados.

Segundo intento · Herencia: extraemos lo común

Identificamos lo que comparten ambas clases y creamos Persona con cedula, nombre y correo. Después hacemos que Cliente y Vendedor hereden de Persona. El teléfono queda en Vendedor, porque es su dato específico.

Segundo modelo UML: Persona contiene los atributos cédula, nombre y correo. Cliente y Vendedor heredan de Persona; Vendedor añade teléfono. La venta conserva referencias a Cliente y Vendedor.
Modelo 2 · Herencia inicial. Compartimos estado mediante una superclase y dos subclases.
Persona.java y Vendedor.java — fragmentos del segundo diseño
public class Persona {
    private long cedula;
    private String nombre;
    private String correo;

    public Persona(long cedula, String nombre, String correo) {
        this.cedula = cedula;
        this.nombre = nombre;
        this.correo = correo;
    }
}

public class Vendedor extends Persona {
    private long telefono;

    public Vendedor(long cedula, String nombre,
                    String correo, long telefono) {
        super(cedula, nombre, correo);
        this.telefono = telefono;
    }
}

extends

Expresa la relación «es un»: un vendedor es una persona. En UML, el triángulo vacío apunta hacia la superclase Persona.

super(...)

Invoca el constructor de Persona para inicializar sus datos comunes. No copia los atributos en Vendedor.

Tercer intento · Simplificamos: ¿necesitamos Cliente como subclase?

Al revisar el modelo advertimos que Cliente no tiene atributos ni comportamientos propios en este sistema. Solo hereda lo que ya define Persona. Por ahora, mantener una subclase vacía agrega complejidad sin resolver una necesidad real.

Decidimos eliminar la clase Cliente y representar a los clientes mediante objetos Persona. Conservamos Vendedor extends Persona, porque su teléfono y su función específica justifican una especialización en este modelo.

Tercer modelo UML: desaparece la clase Cliente. Venta tiene un atributo cliente de tipo Persona y un atributo vendedor de tipo Vendedor. Vendedor hereda de Persona y añade teléfono.
Modelo 3 · Diseño elegido para esta etapa. Venta referencia a Persona como cliente y a Vendedor como vendedor.
Venta.java — referencias en el diseño final
public class Venta {
    private Persona cliente;
    private Vendedor vendedor;

    // Los demás atributos y métodos se incorporan
    // a partir del modelo de la tienda.
}
Idea clave: la herencia no sirve simplemente para reducir líneas de código. Sirve para representar una especialización real. Y tampoco es obligatorio crear una subclase solo porque exista un rol distinto: una persona puede actuar como cliente sin que necesitemos una clase Cliente en esta etapa.

Herencia no es asociación

Un Vendedor es una Persona; por eso hereda de ella. En cambio, una Venta tiene un cliente y un vendedor: esas son relaciones entre objetos, no relaciones de herencia.

Decisión abierta: si más adelante los clientes necesitan reglas o comportamientos específicos, podremos revisar la conveniencia de recuperar Cliente como clase especializada. El diseño responde a los requerimientos presentes, no a todas las posibilidades futuras.

07 · Decidir antes de programar

El UML nos obliga a justificar nuestras elecciones

En nuestros UML de partida

Se representan Cliente, Venta, Producto y DetalleVenta. La asociación entre Venta y Producto lleva información propia en DetalleVenta.

Conservamos las imágenes sin modificar símbolos ni inventar multiplicidades dibujadas.

En una versión posterior del diseño

Podemos establecer una composición Venta–DetalleVenta, una asociación DetalleVenta–Producto y, si el dominio lo necesita, introducir tipos generales y especializados mediante herencia.

Estas son decisiones justificadas, no correcciones silenciosas de los diagramas originales.

Regla útil: antes de elegir una flecha UML, explica la relación en una oración del negocio. Si no puedes explicar la relación, todavía falta análisis.

Progresión del curso

Hoy estudiaremos la semántica de las relaciones y la herencia. En el siguiente SCORM aprenderemos a representar asociaciones múltiples mediante List y a elegir entre ArrayList y LinkedList. Allí introduciremos también el polimorfismo de colecciones y una primera mirada a Set, Map, estructuras ordenadas y métodos de ordenación.

08 · Cierre y verificación

Comprueba si distingues las relaciones

Situación 1: Una venta utiliza un cliente que permanece en el sistema cuando se elimina esa venta. ¿Qué relación describe mejor este vínculo?

Situación 2: Un detalle no tiene sentido sin la venta a la que pertenece y la aplicación decide que una venta controla la vida de sus detalles. ¿Qué relación estamos modelando?

Situación 3: En una ampliación justificada del sistema, Cliente especializa Persona. ¿Qué palabra Java expresa esa relación?

Microentrega de documentación: redacta tres reglas de negocio que justifiquen las relaciones Venta–Cliente, Venta–DetalleVenta y DetalleVenta–Producto. Luego escribe una oración para explicar por qué Venta no debe heredar de Cliente.

Siguiente: SCORM 04 — Colecciones Java, interfaz List, implementaciones, otras colecciones y polimorfismo.

Material en curso