← CC2008

Relaciones entre Clases

Semestre 02, 2026

Introducción

Idea central

En la programación orientada a objetos, las relaciones entre clases permiten definir cómo interactúan y se comunican los distintos componentes de un sistema.

Relaciones comunes

Dependencia: Clase A usa Clase B
Asociación: Clase A tiene-a Clase B (has-a)
Agregación: asociación todo-parte
Composición: asociación fuerte todo-parte
Herencia: Clase A es-una Clase B (is-a)

Dependencia

A usa a B (temporal)

Clase A usa Clase B temporalmente para realizar una operación o tarea específica.

  • No existe un vínculo permanente: la clase dependiente solo requiere de la otra en ciertos métodos o bloques de código.
  • Ocurre cuando A invoca métodos de B o recibe objetos de B como parámetros.

Ejemplo y UML

Pedido → Pago

Un Pedido depende de Pago para procesar un cobro. Sin embargo, el Pedido no guarda un atributo de tipo Pago: solo necesita usarlo en el momento de realizar la transacción.

classDiagram
    Pedido ..> Pago : usa

Clase Pago


public class Pago {
    public void realizar() {
        System.out.println("Pago realizado.");
    }
}
public class Pago {

Declara la clase Pago.

Clase Pago


public class Pago {
    public void realizar() {
        System.out.println("Pago realizado.");
    }
}
public void realizar() { ... }

El método realizar() imprime "Pago realizado." en consola.

Clase Pedido


public class Pedido {
    public void procesarPago(Pago pago) {
        pago.realizar();
    }
}
public class Pedido {

Declara la clase Pedido.

Clase Pedido


public class Pedido {
    public void procesarPago(Pago pago) {
        pago.realizar();
    }
}
public void procesarPago(Pago pago) {

procesarPago() recibe un objeto Pago como parámetro: es un uso temporal.

Clase Pedido


public class Pedido {
    public void procesarPago(Pago pago) {
        pago.realizar();
    }
}
pago.realizar();

Invoca realizar() sobre ese Pago. No lo guarda como atributo.

Main


public class Main {
    public static void main(String[] args) {
        Pago pago = new Pago();

        Pedido pedido = new Pedido();
        pedido.procesarPago(pago);
    }
}
Pago pago = new Pago();

Crea un objeto Pago.

Main


public class Main {
    public static void main(String[] args) {
        Pago pago = new Pago();

        Pedido pedido = new Pedido();
        pedido.procesarPago(pago);
    }
}
Pedido pedido = new Pedido();

Crea un objeto Pedido.

Main


public class Main {
    public static void main(String[] args) {
        Pago pago = new Pago();

        Pedido pedido = new Pedido();
        pedido.procesarPago(pago);
    }
}
pedido.procesarPago(pago);

Pasa el Pago a procesarPago(): la dependencia ocurre solo aquí.

En resumen

Aquí Pedido depende de Pago únicamente en el método procesarPago(). No existe una relación de atributo entre las clases.

Asociación

A tiene-a B (has-a)

Una clase tiene uno o más atributos que son instancias de otra clase. Es más permanente que la dependencia y representa un vínculo lógico entre las clases.

  • Se utiliza cuando un objeto forma parte del estado de otro objeto.

Ejemplo y UML

Carro → Motor

Un Carro tiene un Motor como atributo. La relación existe mientras el Carro exista, pero el Motor puede ser compartido o reemplazado.

classDiagram
    Carro --> Motor : motor

Clase Motor


public class Motor {
    public void encender() {
        System.out.println("Motor encendido.");
    }
}
public class Motor {

Declara la clase Motor.

Clase Motor


public class Motor {
    public void encender() {
        System.out.println("Motor encendido.");
    }
}
public void encender() { ... }

El método encender() imprime "Motor encendido.".

Clase Carro


public class Carro {
    private Motor motor;

    public Carro(Motor motor) {
        this.motor = motor;
    }

    public void arrancar() {
        motor.encender();
    }
}
private Motor motor;

Atributo motor de tipo Motor: un vínculo permanente (has-a).

Clase Carro


public class Carro {
    private Motor motor;

    public Carro(Motor motor) {
        this.motor = motor;
    }

    public void arrancar() {
        motor.encender();
    }
}
public Carro(Motor motor) {
this.motor = motor;

El constructor recibe un Motor y lo guarda como atributo.

Clase Carro


public class Carro {
    private Motor motor;

    public Carro(Motor motor) {
        this.motor = motor;
    }

    public void arrancar() {
        motor.encender();
    }
}
public void arrancar() {
motor.encender();

arrancar() usa el atributo motor para encenderlo.

Main


public class Main {
    public static void main(String[] args) {
        Motor motor = new Motor();

        Carro carro = new Carro(motor);
        carro.arrancar();
    }
}
Motor motor = new Motor();

Crea un objeto Motor.

Main


public class Main {
    public static void main(String[] args) {
        Motor motor = new Motor();

        Carro carro = new Carro(motor);
        carro.arrancar();
    }
}
Carro carro = new Carro(motor);

Crea un Carro pasándole el Motor.

Main


public class Main {
    public static void main(String[] args) {
        Motor motor = new Motor();

        Carro carro = new Carro(motor);
        carro.arrancar();
    }
}
carro.arrancar();

arrancar() enciende el motor guardado.

En resumen

Aquí Carro tiene-a Motor como atributo. La relación es directa y más estable que la dependencia.

Agregación

Todo-parte (débil)

Una clase tiene objetos de otra clase como atributos, pero esas partes pueden existir independientemente del todo.

  • Esta relación se describe como un vínculo "todo-parte" débil.

Ejemplo y UML

Moto → Rueda, Motor

Una Moto está compuesta por Ruedas y un Motor. Si la Moto deja de existir, las Ruedas y el Motor aún pueden existir por separado.

classDiagram
    Moto o-- Rueda : ruedas
    Moto o-- Motor : motor

Clases Rueda y Motor


public class Rueda {
    public void girar() {
        System.out.println("La rueda está girando.");
    }
}

public class Motor {
    public void encender() {
        System.out.println("Motor encendido.");
    }
}

Cada parte es una clase independiente: una Rueda gira y un Motor enciende, sin necesitar a la Moto.

Clase Moto


public class Moto {
    private Rueda[] ruedas;
    private Motor motor;

    public Moto(Rueda[] ruedas, Motor motor) {
        this.ruedas = ruedas;
        this.motor = motor;
    }

    public void arrancar() {
        motor.encender();
        for (Rueda rueda : ruedas) {
            rueda.girar();
        }
    }
}
private Rueda[] ruedas;
private Motor motor;

Atributos: un arreglo de Ruedas y un Motor.

Clase Moto


public class Moto {
    private Rueda[] ruedas;
    private Motor motor;

    public Moto(Rueda[] ruedas, Motor motor) {
        this.ruedas = ruedas;
        this.motor = motor;
    }

    public void arrancar() {
        motor.encender();
        for (Rueda rueda : ruedas) {
            rueda.girar();
        }
    }
}
public Moto(Rueda[] ruedas, Motor motor) {

El constructor recibe las partes ya creadas desde afuera; por eso pueden existir sin la Moto.

Clase Moto


public class Moto {
    private Rueda[] ruedas;
    private Motor motor;

    public Moto(Rueda[] ruedas, Motor motor) {
        this.ruedas = ruedas;
        this.motor = motor;
    }

    public void arrancar() {
        motor.encender();
        for (Rueda rueda : ruedas) {
            rueda.girar();
        }
    }
}
public void arrancar() { ... }

arrancar() enciende el motor y hace girar cada rueda.

Main


public class Main {
    public static void main(String[] args) {
        Rueda[] ruedas = { new Rueda(), new Rueda() };
        Motor motor = new Motor();

        Moto moto = new Moto(ruedas, motor);
        moto.arrancar();
    }
}
Rueda[] ruedas = { new Rueda(), new Rueda() };

Crea las Ruedas por separado.

Main


public class Main {
    public static void main(String[] args) {
        Rueda[] ruedas = { new Rueda(), new Rueda() };
        Motor motor = new Motor();

        Moto moto = new Moto(ruedas, motor);
        moto.arrancar();
    }
}
Motor motor = new Motor();

Crea el Motor por separado.

Main


public class Main {
    public static void main(String[] args) {
        Rueda[] ruedas = { new Rueda(), new Rueda() };
        Motor motor = new Motor();

        Moto moto = new Moto(ruedas, motor);
        moto.arrancar();
    }
}
Moto moto = new Moto(ruedas, motor);

Crea la Moto recibiendo partes que ya existían.

Main


public class Main {
    public static void main(String[] args) {
        Rueda[] ruedas = { new Rueda(), new Rueda() };
        Motor motor = new Motor();

        Moto moto = new Moto(ruedas, motor);
        moto.arrancar();
    }
}
moto.arrancar();

Arranca la moto.

En resumen

Aquí Moto agrega Ruedas y Motor. Aunque la Moto desaparezca, las Ruedas y el Motor pueden seguir existiendo.

Composición

Todo-parte (fuerte)

Es una variante de la agregación donde las partes no pueden existir independientemente del todo. Si el objeto contenedor se destruye, también se destruyen sus partes.

Ejemplo y UML

Casa → Habitación

Una Casa tiene Habitaciones. Las habitaciones no tienen sentido fuera de la casa.

classDiagram
    Casa *-- Habitacion : habitaciones

Clase Habitacion


public class Habitacion {
    public void abrirPuerta() {
        System.out.println("Puerta abierta.");
    }
}
public class Habitacion {

Declara la clase Habitacion.

Clase Habitacion


public class Habitacion {
    public void abrirPuerta() {
        System.out.println("Puerta abierta.");
    }
}
public void abrirPuerta() { ... }

El método abrirPuerta() imprime "Puerta abierta.".

Clase Casa


public class Casa {
    private Habitacion[] habitaciones;

    public Casa() {
        habitaciones = new Habitacion[5];
        for (int i = 0; i < 5; i++) {
            habitaciones[i] = new Habitacion();
        }
    }

    public void recorrerCasa() {
        for (Habitacion h : habitaciones) {
            h.abrirPuerta();
        }
    }
}
private Habitacion[] habitaciones;

Atributo: un arreglo de Habitaciones.

Clase Casa


public class Casa {
    private Habitacion[] habitaciones;

    public Casa() {
        habitaciones = new Habitacion[5];
        for (int i = 0; i < 5; i++) {
            habitaciones[i] = new Habitacion();
        }
    }

    public void recorrerCasa() {
        for (Habitacion h : habitaciones) {
            h.abrirPuerta();
        }
    }
}
public Casa() { ... }

El constructor: la Casa crea sus propias habitaciones.

Clase Casa


public class Casa {
    private Habitacion[] habitaciones;

    public Casa() {
        habitaciones = new Habitacion[5];
        for (int i = 0; i < 5; i++) {
            habitaciones[i] = new Habitacion();
        }
    }

    public void recorrerCasa() {
        for (Habitacion h : habitaciones) {
            h.abrirPuerta();
        }
    }
}
for (int i = 0; i < 5; i++) {

Crea 5 Habitacion dentro de la Casa; nacen con ella.

Clase Casa


public class Casa {
    private Habitacion[] habitaciones;

    public Casa() {
        habitaciones = new Habitacion[5];
        for (int i = 0; i < 5; i++) {
            habitaciones[i] = new Habitacion();
        }
    }

    public void recorrerCasa() {
        for (Habitacion h : habitaciones) {
            h.abrirPuerta();
        }
    }
}
public void recorrerCasa() { ... }

recorrerCasa() abre la puerta de cada habitación.

Main


public class Main {
    public static void main(String[] args) {
        Casa casa = new Casa();
        casa.recorrerCasa();
    }
}
Casa casa = new Casa();

Al crear la Casa se crean automáticamente sus Habitaciones.

Main


public class Main {
    public static void main(String[] args) {
        Casa casa = new Casa();
        casa.recorrerCasa();
    }
}
casa.recorrerCasa();

Recorre la casa. Si la Casa se destruye, sus Habitaciones también.

En resumen

Aquí Casa compone Habitaciones. Las habitaciones son creadas y destruidas junto con la Casa.

Herencia

A es-una B (is-a)

Relación Clase A es-una Clase B.

Se cubre a fondo en la lección de Herencia.

Resumen

RelaciónDefiniciónEjemplo
DependenciaUso temporal de otra clasePedido → Pago
AsociaciónAtributo de una clase es otra claseCarro → Motor
AgregaciónTodo-parte (partes independientes)Moto → Rueda
ComposiciónTodo-parte fuerte (partes dependientes)Casa → Habitacion