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 02

De las clases a los objetos

En la tienda de cómics «La Viñeta» ya identificamos entidades y asociaciones. Ahora vamos a convertir ese análisis en clases Java, repartir responsabilidades y crear objetos que colaboran.

Clases y objetosEstado y comportamientoEncapsulamientoRelacionesCET1
01 · Punto de partida

El diagrama no es todavía el programa

El SCORM anterior nos dejó dos miradas sobre el mismo problema: un modelo conceptual para comprender el negocio y un modelo de diseño para acercarnos a Java.

Diagrama conceptual de Cliente, Venta, Producto y DetalleVenta como clase de asociación
Modelo conceptual. Expresa quién participa en la venta y por qué es necesario guardar datos sobre cada producto vendido.
Diagrama de diseño de Cliente, Venta, Producto y DetalleVenta con atributos y tipos
Modelo de diseño. Agrega atributos y tipos; representa referencias y una colección de detalles para programar.
Pregunta de diseño: ¿Dónde debe vivir la cantidad de ejemplares de un cómic vendidos en una compra? En DetalleVenta, porque pertenece a esa operación, no al producto del catálogo en general.

Conservamos los diagramas originales. Para los ejemplos que siguen elegiremos determinadas firmas Java; son decisiones de implementación y no datos nuevos del modelo conceptual.

02 · Una distinción esencial

La clase describe; el objeto existe

Una clase define qué información y operaciones tienen los objetos de un mismo tipo. Un objeto es una instancia concreta, con valores propios.

Clase Producto→ new Producto(...)Objeto p1+Objeto p2
p1 : Producto
  • codigo = 101
  • nombre = "Mafalda 1"
  • precio = 450.0
  • stock = 8
p2 : Producto
  • codigo = 102
  • nombre = "El Eternauta"
  • precio = 790.0
  • stock = 3

Ambos tienen el mismo tipo y la misma estructura, pero no son el mismo objeto ni tienen el mismo estado.

Producto.java — primera versión
public class Producto {
    private long codigo;
    private String nombre;
    private double precio;
    private int stock;

    public Producto(long codigo, String nombre, double precio, int stock) {
        this.codigo = codigo;
        this.nombre = nombre;
        this.precio = precio;
        this.stock = stock;
    }
}

El constructor recibe los valores iniciales. this.codigo se refiere al atributo del objeto; codigo es el parámetro recibido.

03 · Estado

Los atributos representan información del dominio

Producto

El ejemplar del catálogo tiene código, nombre, precio y stock. El stock representa unidades disponibles, no unidades compradas en una venta concreta.

DetalleVenta

Registra qué producto figura en una venta, cuántas unidades se compraron y qué precio unitario se aplicó.

EntidadAtributos principales¿Por qué?
Clientecédula, nombre, correoIdentificar al comprador.
Ventanúmero, fecha, cliente, detallesRepresentar una transacción.
Productocódigo, nombre, precio, stockDescribir el catálogo.
DetalleVentaproducto, cantidad, precioUnitarioRepresentar cada renglón de la compra.
No todo sustantivo exige una clase. Antes de crear una clase, comprueba si representa una entidad con identidad, estado o responsabilidades propias en el problema.
04 · Comportamiento

¿Qué debe saber hacer cada clase?

No diseñamos clases únicamente para guardar datos. También distribuimos responsabilidades: acciones coherentes con lo que cada objeto representa.

Producto

Informar su precio y stock; permitir modificaciones controladas de sus datos.

DetalleVenta

Calcular el subtotal del renglón: cantidad por precio unitario.

Venta

Conservar sus detalles y calcular el total sumando los subtotales.

DetalleVenta.java — responsabilidad propia
public class DetalleVenta {
    private Producto producto;
    private int cantidad;
    private double precioUnitario;

    public DetalleVenta(Producto producto, int cantidad, double precioUnitario) {
        this.producto = producto;
        this.cantidad = cantidad;
        this.precioUnitario = precioUnitario;
    }

    public double calcularSubtotal() {
        double subtotal = cantidad * precioUnitario;
        return subtotal;
    }
}
Decisión importante: precioUnitario se conserva en el detalle, incluso si luego cambia el precio del catálogo. Así podemos representar el precio utilizado en esa venta.
05 · Encapsulamiento

Atributos privados y operaciones públicas

Declarar los atributos private evita que otra clase modifique directamente el estado. Exponemos métodos públicos para consultar o cambiar lo que corresponda.

Sin control

Otra clase modifica un precio directamente y puede introducir valores incorrectos.

producto.precio = -50;
→

Con encapsulamiento

El objeto decide qué operación pública ofrece y qué condiciones aplica.

producto.setPrecio(450);
Producto.java — métodos accesibles
public long getCodigo() {
    return codigo;
}

public String getNombre() {
    return nombre;
}

public double getPrecio() {
    return precio;
}

public int getStock() {
    return stock;
}

public void setPrecio(double nuevoPrecio) {
    if (nuevoPrecio >= 0 && Double.isFinite(nuevoPrecio)) {
        this.precio = nuevoPrecio;
    }
}

El ejemplo introduce una comprobación pequeña para ilustrar la idea. Más adelante veremos una capa de servicio que concentrará las reglas de negocio de la aplicación; no debemos confundir ambas responsabilidades.

Observación: aquí el método no cambia el precio si el dato es inválido. En una aplicación más completa podríamos comunicar ese error de forma explícita. Estudiaremos las excepciones posteriormente.
06 · Asociaciones

Los objetos colaboran mediante referencias

En Java, una relación entre objetos puede implementarse conservando una referencia a otro objeto. Cuando una venta tiene varios detalles, podemos usar una colección de referencias.

Cliente← comprador deVenta→ contieneList<DetalleVenta>→ referenciaProducto

Una venta, un cliente

Un campo Cliente cliente identifica al comprador de esa venta.

Una venta, varios detalles

Una lista permite registrar diferentes productos y cantidades dentro de una misma venta.

Venta.java — estructura mínima
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class Venta {
    private int numero;
    private LocalDate fecha;
    private Cliente cliente;
    private List<DetalleVenta> detalles;

    public Venta(int numero, LocalDate fecha, Cliente cliente) {
        this.numero = numero;
        this.fecha = fecha;
        this.cliente = cliente;
        this.detalles = new ArrayList<>();
    }

    public void agregarDetalle(DetalleVenta detalle) {
        detalles.add(detalle);
    }

    public double calcularTotal() {
        double total = 0;
        for (DetalleVenta detalle : detalles) {
            total += detalle.calcularSubtotal();
        }
        return total;
    }
}
Una decisión de diseño explícita: el diagrama escribe Date. Aquí usamos LocalDate, disponible en Java moderno, para representar una fecha sin hora. Es una elección de implementación, no una modificación del diagrama original.
07 · Instancias y mensajes

La historia completa, en objetos

Supongamos que Lucía compra dos ejemplares de «Mafalda 1» y uno de «El Eternauta». Creamos los productos, un cliente, la venta y sus detalles.

Main.java — ejemplo didáctico de uso
import java.time.LocalDate;

public class Main {
    public static void main(String[] args) {
        Producto mafalda = new Producto(101, "Mafalda 1", 450, 8);
        Producto eternauta = new Producto(102, "El Eternauta", 790, 3);

        Cliente lucia = new Cliente(49876543L, "Lucía Pérez", "lucia@ejemplo.com");

        Venta venta = new Venta(25, LocalDate.of(2026, 10, 25), lucia);
        DetalleVenta d1 = new DetalleVenta(mafalda, 2, 450);
        DetalleVenta d2 = new DetalleVenta(eternauta, 1, 790);

        venta.agregarDetalle(d1);
        venta.agregarDetalle(d2);

        System.out.println("Total: $" + venta.calcularTotal());
    }
}
Cliente.java — clase mínima para ejecutar el ejemplo
public class Cliente {
    private long cedula;
    private String nombre;
    private String correo;

    public Cliente(long cedula, String nombre, String correo) {
        this.cedula = cedula;
        this.nombre = nombre;
        this.correo = correo;
    }
}
Detalle 1: 2 × 450 = 900+Detalle 2: 1 × 790 = 790=Total: $1690

El Main es solo un ejemplo para visualizar la colaboración entre objetos. Todavía no hay Swing, DAO ni base de datos; esos componentes aparecerán más adelante cuando hagan falta.

Precisión: para facilitar la comprensión mantuvimos double, como en el modelo que estamos trabajando. En sistemas monetarios de producción es preferible BigDecimal.
08 · Lo que queda construido

Del modelo OO a responsabilidades concretas

ClaseDefine atributos, constructor y métodos para un tipo de objeto.
ObjetoEs una instancia con valores particulares y referencias a otros objetos.
ColaboraciónLos objetos se comunican mediante llamadas a métodos; cada uno cumple su responsabilidad.

Comprobación rápida

Si una venta contiene tres productos diferentes, ¿qué objeto debería calcular el importe de cada renglón?

Microentrega de documentación: elabora una ficha CRC de Venta y DetalleVenta: nombre de clase, dos responsabilidades y sus colaboradores. Acompáñala con un ejemplo de objeto concreto de cada una.

Lo siguiente: profundizaremos en encapsulamiento, relaciones y colecciones, y veremos cómo las decisiones OO nos permiten construir programas más fáciles de ampliar.

Material en curso