Al cerrar el módulo 2 hiciste un diagnóstico incómodo de tu propio programa: mayorRetraso, empleadoMayorRetraso y libroMayorRetraso son tres variables sueltas que describen una sola cosa, y nada impide actualizar una y olvidar las otras dos. Ese diagnóstico no es un detalle de estilo: es el síntoma de un límite estructural del estilo de programación que has usado hasta ahora. Un programa procedimental organiza el código en pasos; cuando los pasos crecen, los datos relacionados se dispersan por variables independientes y nadie garantiza que sigan siendo coherentes entre sí. La programación orientada a objetos (POO) propone otra organización: agrupar los datos con las operaciones que los gobiernan, en unidades llamadas objetos, de modo que un dato incoherente sea imposible de construir. Esta lección no escribe todavía la clase Libro —eso llega en la siguiente—; su trabajo es que entiendas qué problema resuelve la POO, con qué vocabulario se piensa y cómo se modela el dominio de BiblioTech antes de teclear una sola llave.

Contenido

  1. El punto de partida: BiblioTechApp 2.0 vista de cerca
  2. Por qué el código procedimental se degrada al crecer
  3. Qué es la orientación a objetos
  4. Clase frente a objeto: el plano y la casa
  5. Identidad, estado y comportamiento
  6. Instancia y referencia
  7. Los cuatro pilares en un vistazo
  8. Modelar el dominio: de los sustantivos a las clases
  9. El modelo objetivo de BiblioTech
  10. Relaciones entre clases: asociación, composición y agregación
  11. Ventajas reales de la POO... y sus costes
  12. Errores Comunes y Consejos
  13. Ejercicios

  1. El punto de partida: BiblioTechApp 2.0 vista de cerca

Tu aplicación funciona. Muestra un menú, valida entradas, aplica las reglas de negocio de Nexus Software y emite recibos alineados. Pero mira el bloque de declaraciones con el que arranca main:

// Reglas de negocio
final int    DIAS_PRESTAMO = 15;
final double TARIFA_DIARIA = 0.25;
final double MULTA_MAXIMA  = 20.0;
final int    UMBRAL_LEVE   = 7;

// Datos de la operacion en curso
String empleado;
String titulo;
String isbn;
int    diasTranscurridos;
int    diasRetraso;
double multa;
String estado;
String gravedad;

// Estadisticas de sesion
int    devoluciones          = 0;
int    prestamos             = 0;
double recaudacion           = 0.0;
int    mayorRetraso          = 0;
String empleadoMayorRetraso  = "-";
String libroMayorRetraso     = "-";

Cuenta lo que hay ahí: veinte variables en el mismo ámbito, todas visibles desde cualquier punto de las doscientas líneas de main, todas modificables desde cualquier punto, y ninguna relación explícita entre ellas. El compilador no sabe que titulo e isbn describen el mismo libro. No sabe que mayorRetraso y empleadoMayorRetraso deben cambiar a la vez. No sabe que multa nunca puede superar MULTA_MAXIMA. Todo eso vive en tu cabeza y en los comentarios.

  1. Por qué el código procedimental se degrada al crecer

El estilo procedimental —datos por un lado, pasos por otro— funciona perfectamente en programas pequeños. El problema aparece cuando el programa crece, y se manifiesta siempre de las mismas cuatro formas:

Síntoma Cómo se ve en BiblioTech Consecuencia
Dispersión de datos titulo, isbn, autor describen un libro pero son variables independientes Nada garantiza que el ISBN corresponda al título
Estado global mutable Las veinte variables son visibles en todo main Cualquier línea puede corromper cualquier dato
Reglas duplicadas El tope de multa se aplica en la rama de devolución y en la tabla de escala Si cambia la regla, hay que buscar todas las copias
Escalado imposible Para dos libros harían falta titulo1, isbn1, titulo2, isbn2... El código crece linealmente con los datos

El cuarto síntoma es el más revelador. Pregúntate cómo registrarías dos devoluciones simultáneas con el diseño actual. La respuesta honesta es: duplicando variables. Y con tres, triplicándolas. Ese camino no lleva a ninguna parte.

flowchart LR
    subgraph PROC["Procedimental"]
        D1["titulo"]
        D2["isbn"]
        D3["diasRetraso"]
        D4["multa"]
        F1["calcular"]
        F2["imprimir"]
        F1 -.-> D1
        F1 -.-> D3
        F2 -.-> D2
        F2 -.-> D4
    end
    subgraph OO["Orientado a objetos"]
        O1["Libro
        titulo, isbn
        estaDisponible()"]
        O2["Prestamo
        diasRetraso, multa
        calcularMulta()"]
        O2 --> O1
    end

A la izquierda, datos y funciones se cruzan en todas direcciones. A la derecha, cada dato vive dentro de la unidad que sabe qué hacer con él.

  1. Qué es la orientación a objetos

La POO es un paradigma: una manera de organizar un programa. Su idea central cabe en una frase:

Un programa es un conjunto de objetos que colaboran enviándose mensajes; cada objeto guarda sus propios datos y es el único responsable de las operaciones que los modifican.

Tres consecuencias inmediatas:

  • Los datos dejan de ser pasivos. Un Prestamo no es una tupla de valores que alguien inspecciona desde fuera; es una entidad a la que le preguntas cuánta multa corresponde.
  • Las reglas viven junto a los datos que gobiernan. La regla "la multa nunca supera 20 €" pasa a ser un asunto interno de Prestamo, no una línea perdida en main.
  • El programa se lee en el vocabulario del negocio. prestamo.calcularMulta() se entiende sin conocer la implementación; multa = diasRetraso * TARIFA_DIARIA; if (multa >= MULTA_MAXIMA) multa = MULTA_MAXIMA; obliga a leer aritmética para deducir la intención.

Java es un lenguaje orientado a objetos por diseño: salvo los ocho tipos primitivos que viste en el módulo 1, todo lo que has manipulado ya era un objeto. String, Scanner o System.out son objetos; scanner.nextLine() es exactamente un mensaje enviado a un objeto. Llevas dos módulos usando POO sin saberlo; lo que empieza ahora es escribir tus propios tipos.

  1. Clase frente a objeto: el plano y la casa

Esta es la distinción fundamental, y conviene fijarla con una analogía antes de ver sintaxis.

Una clase es un plano de arquitecto: describe qué tendrá cada casa (número de habitaciones, superficie) y qué se podrá hacer con ella (abrir la puerta, encender la luz). El plano no es una casa: no puedes vivir en él, no tiene dirección postal y no se puede pintar de azul.

Un objeto es una casa construida a partir de ese plano: ocupa un lugar concreto, tiene valores concretos (140 m², pintada de azul) y se puede usar. Del mismo plano se construyen mil casas, todas con la misma estructura y cada una con sus propios valores.

Concepto Clase Objeto
Naturaleza Plantilla, definición, tipo Ejemplar concreto en memoria
Cuándo existe En tiempo de compilación (es código) En tiempo de ejecución (ocupa memoria)
Cuántos hay Uno por definición Tantos como se creen
En BiblioTech Libro "Java Efectivo", "Refactorización"
Analogía El plano, el molde, la receta La casa, la pieza, el pastel

Traducido al dominio: escribirás una clase Libro y crearás con ella tres objetos, uno para "Java Efectivo" (ISBN 978-0000000001), otro para "Patrones de Diseño" (978-0000000002) y otro para "Refactorización" (978-0000000003). Los tres comparten estructura —todos tienen título, autor, ISBN, año y disponibilidad— y difieren en los valores.

  1. Identidad, estado y comportamiento

Todo objeto se describe con tres propiedades. Interiorizarlas te ahorrará confusiones durante todo el módulo.

  • Identidad: qué objeto es, con independencia de sus valores. Dos ejemplares físicos de "Java Efectivo" en la estantería son objetos distintos aunque compartan título e ISBN. En Java la identidad es la posición en memoria, y es lo que compara == (lo viste en el módulo 1 con el string pool, y volverá en 03-09).
  • Estado: los valores que el objeto guarda en un instante. El estado de un Libro incluye titulo, autor, isbn, anioPublicacion y disponible. El estado cambia: disponible pasa de true a false cuando alguien se lo lleva.
  • Comportamiento: las operaciones que el objeto sabe realizar. Un Prestamo sabe calcular sus días de retraso, su multa y su gravedad.

Aplicado al vocabulario que ya usas:

Clase Estado (atributos) Comportamiento (operaciones)
Libro titulo, autor, isbn, anioPublicacion, disponible prestarse, devolverse, decir si está disponible
Empleado nombre, identificador, préstamos acumulados registrar un préstamo, decir cuántos acumula
Prestamo libro, empleado, diasTranscurridos calcular diasRetraso, multa, gravedad, estado

Fíjate en un detalle que gobernará todo el módulo: la columna de la derecha es lo que hoy está suelto en main. La POO no inventa comportamiento nuevo; lo muda de sitio, del procedimiento al objeto que le corresponde.

  1. Instancia y referencia

Dos palabras que oirás constantemente y que conviene separar desde ya:

  • Instancia es sinónimo de objeto: el ejemplar concreto creado a partir de una clase. "Crear una instancia de Libro" y "crear un objeto Libro" significan lo mismo.
  • Referencia es la variable con la que llegas a ese objeto. No es el objeto: es la dirección donde vive.

La distinción importa porque en Java nunca manipulas objetos directamente, siempre a través de referencias. Cuando escribes:

Libro javaEfectivo = new Libro();

ocurren tres cosas independientes: se reserva memoria para un objeto Libro en el heap (lo llamábamos "montículo" en el módulo 1), se declara una variable javaEfectivo en la pila, y se guarda en esa variable la dirección del objeto. Una consecuencia inmediata, que la lección 03-02 desarrolla con detalle: dos referencias pueden apuntar al mismo objeto, y entonces un cambio hecho a través de una se ve a través de la otra.

  1. Los cuatro pilares en un vistazo

La POO se sostiene sobre cuatro ideas. Aquí las tienes en una frase cada una, con la lección donde se desarrollan; no intentes dominarlas ahora, solo reconocer los nombres cuando aparezcan.

Pilar En una frase Ejemplo en BiblioTech Lección
Encapsulamiento El objeto oculta su representación interna y solo expone operaciones controladas Nadie puede asignar una multa arbitraria: se calcula al devolver 03-07
Herencia Una clase puede definirse como una especialización de otra y reutilizar lo que esta ya define Libro, Revista y Dvd son tipos de Material prestable 03-05
Polimorfismo Una misma llamada produce comportamientos distintos según el tipo real del objeto material.calcularMulta() cobra 0,25 €/día si es libro y 0,50 €/día si es DVD 03-06
Abstracción Se modela solo lo esencial para el problema y se oculta el resto A BiblioTech le importa el ISBN de un libro, no su peso ni su color de portada 03-08

Un apunte de honestidad: estos cuatro términos se recitan mucho y se entienden poco. Al final del módulo no los habrás memorizado, los habrás usado, que es la única forma de aprenderlos.

  1. Modelar el dominio: de los sustantivos a las clases

Antes de escribir código hay que decidir qué clases existen. Existe una técnica sencilla y sorprendentemente eficaz para empezar: subrayar los sustantivos del enunciado del problema. Este es el enunciado de BiblioTech tal como lo daría el departamento de Nexus Software:

La biblioteca técnica interna gestiona los libros que los empleados toman en préstamo. Cada libro tiene título, autor, ISBN y año de publicación, y puede estar disponible o no. Un préstamo dura 15 días; pasado ese plazo se acumulan días de retraso que generan una multa de 0,25 € diarios con un máximo de 20 €. Un retraso de hasta 7 días se considera leve; por encima, grave.

Sustantivos candidatos: biblioteca, libro, empleado, préstamo, título, autor, ISBN, año, días, multa, retraso.

Ahora se filtran con tres criterios:

  1. ¿Tiene identidad propia y estado que cambia? → es candidato a clase. Libro, Empleado, Préstamo lo cumplen.
  2. ¿Es un simple valor descriptivo de otra cosa? → es candidato a atributo. Título, ISBN, año describen un libro; días de retraso y multa describen un préstamo.
  3. ¿Es el sistema entero o un concepto vago? → normalmente no es una clase de dominio. Biblioteca es el sistema; lo que aparecerá más adelante es un Catalogo que guarda materiales y un GestorPrestamos que orquesta operaciones (módulos 5 y siguientes).

Resultado del filtrado para este módulo: tres clases, Libro, Empleado y Prestamo, exactamente las que se anunciaron al cerrar el módulo 2.

Y una pregunta que separa un modelo bueno de uno mediocre: ¿de quién es cada responsabilidad? Una responsabilidad mal colocada compila igual, pero envenena el diseño.

Responsabilidad ¿De quién? Por qué
Saber su ISBN Libro Es un dato intrínseco del libro
Saber si está prestado Libro Es un estado del ejemplar
Calcular los días de retraso Prestamo Depende del plazo y del tiempo transcurrido, no del libro
Calcular la multa Prestamo Es una consecuencia del retraso de esa operación
Saber cuántos préstamos acumula Empleado Es historial de la persona
Imprimir el recibo Ni Libro ni Prestamo Es presentación; se separa del dominio (lección 03-08)

  1. El modelo objetivo de BiblioTech

Este es el modelo al que llegarás al terminar el módulo. Guárdalo como mapa: cada lección añade una pieza.

classDiagram
    class Libro {
        -String titulo
        -String autor
        -String isbn
        -int anioPublicacion
        -boolean disponible
        +estaDisponible() boolean
        +prestar() void
        +devolver() void
        +toString() String
        +equals(Object) boolean
    }
    class Empleado {
        -String nombre
        -String identificador
        -int prestamosAcumulados
        +registrarPrestamo() void
        +getPrestamosAcumulados() int
        +toString() String
    }
    class Prestamo {
        -Libro libro
        -Empleado empleado
        -int diaPrestamo
        -int diaVencimiento
        -int diasTranscurridos
        +calcularDiasRetraso() int
        +calcularMulta() double
        +clasificarGravedad() String
        +registrarDevolucion(int) void
        +toString() String
    }
    Prestamo --> Libro : libro prestado
    Prestamo --> Empleado : solicitante

Léelo así: un Prestamo conoce un Libro y un Empleado; ni el libro ni el empleado necesitan conocer el préstamo. Las flechas indican la dirección de la dependencia, y esa dirección es una decisión de diseño, no un accidente.

En la lección 03-05 este diagrama crecerá hacia arriba: aparecerá una clase Material de la que Libro, Revista y Dvd serán especializaciones.

  1. Relaciones entre clases: asociación, composición y agregación

Las clases rara vez viven aisladas. Hay tres formas típicas de relacionarse, además de la herencia:

Relación Significado Duración del vínculo Ejemplo en BiblioTech
Asociación "usa" o "conoce a" Independiente Prestamo conoce al Empleado que lo solicita
Agregación "tiene un" con partes que sobreviven al todo El todo puede desaparecer y las partes siguen Un Catalogo agrega Libros: si se borra el catálogo, los libros existen igual
Composición "está formado por" con partes que mueren con el todo Las partes no tienen sentido sin el todo Un Prestamo compone su propio registro de fechas y estado
Herencia "es un" Estructural, en tiempo de compilación Un Libro es un Material (lección 03-05)

La prueba práctica para distinguir agregación de composición es preguntarse: si destruyo el objeto contenedor, ¿tiene sentido que la parte siga existiendo? Si la respuesta es sí, es agregación; si es no, composición. Un libro sobrevive al catálogo que lo lista; el desglose interno de una multa no sobrevive al préstamo que la generó.

No te obsesiones con estas etiquetas: en código Java, asociación, agregación y composición se escriben casi igual (un campo que referencia a otro objeto). Su valor está en el diseño y en la conversación con otros desarrolladores.

  1. Ventajas reales de la POO... y sus costes

Los cursos suelen enumerar solo la columna izquierda. Un profesional necesita las dos.

Ventajas Costes
Los datos relacionados viajan juntos y no se descoordinan Indirección: para saber qué hace prestamo.calcularMulta() hay que abrir otro fichero
Las reglas de negocio están en un único lugar Ceremonia: más ficheros, más líneas para lo mismo en programas pequeños
El código se lee en el vocabulario del negocio Sobrediseño: es fácil crear jerarquías de siete niveles para un problema de dos
Añadir un tipo nuevo no obliga a tocar el código existente (03-06) Curva de aprendizaje: herencia y polimorfismo tienen trampas sutiles
Cada clase se puede probar por separado (módulo 11) Acoplamiento oculto: una clase base mal diseñada rompe a todas sus hijas (03-05)

Regla práctica que te servirá durante años: la POO paga cuando el programa tiene que crecer y cambiar. Un script de treinta líneas que se ejecuta una vez no necesita clases. BiblioTech sí: va a crecer durante diez módulos más.

Errores Comunes y Consejos

  • Confundir clase con objeto al hablar. "Voy a modificar el libro" es ambiguo: ¿la clase Libro (el plano, y afecta a todos) o el objeto javaEfectivo (un ejemplar)? Acostúmbrate a nombrar la clase en mayúscula y singular (Libro) y los objetos con nombres concretos (javaEfectivo).
  • Convertir en clase todo sustantivo del enunciado. No todo lo nombrable merece una clase. titulo es un String, no una clase Titulo. Aplica el filtro del apartado 8: identidad + estado que cambia.
  • Crear clases que solo guardan datos. Una clase con cinco campos y diez getters, sin ningún comportamiento, es una estructura de datos disfrazada (se le llama modelo anémico). Pregúntate siempre qué sabe hacer la clase, no solo qué contiene.
  • Colocar el comportamiento en la clase equivocada. Si Libro calculase multas, tendría que conocer plazos, tarifas y días transcurridos, datos que no le pertenecen. Cada operación va donde están los datos que necesita.
  • Empezar por la herencia. Es el pilar más llamativo y el más peligroso. Modela primero clases planas que funcionen; la jerarquía aparecerá sola cuando la necesites (lección 03-05).
  • Consejo: dibuja antes de teclear. Cinco minutos de diagrama de clases en papel ahorran horas de refactorización. No necesitas UML formal: cajas con nombre, atributos y flechas bastan.
  • Consejo: nombra en el idioma del negocio. Prestamo, Libro y Empleado son mejores nombres que DataRecord, Item o Manager, porque cualquiera de Nexus Software los entiende sin explicación.

Ejercicios

Ejercicio 1: identificar clases, atributos y responsabilidades

Nexus Software quiere ampliar BiblioTech con un módulo de salas de reuniones:

Los empleados reservan salas de reuniones. Cada sala tiene un nombre, una capacidad máxima de personas y un equipamiento (proyector sí o no). Una reserva la hace un empleado para una sala, en una franja horaria concreta, con un número de asistentes que no puede superar la capacidad de la sala. Una reserva puede cancelarse.

Sin escribir código Java completo:

  1. Enumera los sustantivos y clasifícalos en clase, atributo o descartado, justificando cada decisión.
  2. Escribe una tabla de responsabilidades: qué debe saber hacer cada clase.
  3. Indica qué tipo de relación (asociación, agregación o composición) hay entre Reserva y Sala, y entre Reserva y Empleado.

Ejercicio 2: diagrama y esqueletos de clase

Con el resultado del ejercicio 1:

  1. Dibuja el diagrama classDiagram de mermaid del modelo de salas.
  2. Escribe los esqueletos de las clases (solo la declaración y los campos, con comentarios donde irían las operaciones). No implementes nada: la sintaxis completa llega en 03-02.

Ejercicio 3: detectar responsabilidades mal colocadas

Un compañero propone este diseño para BiblioTech. Señala tres decisiones que consideres erróneas y explica dónde debería vivir cada responsabilidad:

class Libro {
    String titulo;
    String isbn;
    double multaDelUltimoPrestamo;   // (a)
    String nombreDelEmpleadoActual;  // (b)
    void imprimirReciboDeDevolucion() { }  // (c)
    void guardarEnFichero() { }            // (d)
}

Soluciones

Solución 1

1. Clasificación de sustantivos

Sustantivo Clasificación Justificación
Empleado Clase Ya existe en el modelo; tiene identidad y estado propio
Sala Clase Tiene identidad (cada sala es distinta) y estado (equipamiento, capacidad)
Reserva Clase Tiene identidad, estado que cambia (activa/cancelada) y comportamiento (cancelarse)
Nombre, capacidad, proyector Atributos de Sala Son valores que describen la sala, no entidades con vida propia
Franja horaria, asistentes Atributos de Reserva Describen una reserva concreta
Módulo, sistema Descartados Son el programa entero, no conceptos del dominio

Un matiz profesional: franja horaria podría llegar a ser una clase propia (Franja, con hora de inicio y fin, y capaz de decir si se solapa con otra). Es una decisión legítima, pero prematura ahora: empieza por atributos y promueve a clase solo cuando el concepto acumule comportamiento propio.

2. Responsabilidades

Clase Debe saber
Sala Su nombre, su capacidad y si tiene proyector; decir si admite un número de asistentes
Empleado Su nombre e identificador; cuántas reservas acumula
Reserva Qué sala, qué empleado, qué franja y cuántos asistentes; validar que caben; cancelarse; decir si está activa

Observa que "decir si admite N asistentes" es de Sala, porque la capacidad es un dato suyo; en cambio "validar que caben" es de Reserva, porque solo la reserva conoce el número de asistentes. Cada una aporta lo que sabe.

3. Relaciones

  • ReservaSala: asociación (o agregación). La sala existe antes y después de la reserva; cancelar una reserva no destruye la sala.
  • ReservaEmpleado: asociación. El empleado tiene vida propia en la empresa.

No hay composición evidente en este modelo, salvo que la franja horaria se modelase como objeto interno de la reserva: entonces sí sería composición, porque esa franja no significa nada fuera de su reserva.

Solución 2

Diagrama

classDiagram
    class Sala {
        -String nombre
        -int capacidadMaxima
        -boolean tieneProyector
        +admite(int asistentes) boolean
    }
    class Empleado {
        -String nombre
        -String identificador
        -int reservasAcumuladas
    }
    class Reserva {
        -Sala sala
        -Empleado solicitante
        -int horaInicio
        -int horaFin
        -int asistentes
        -boolean activa
        +cancelar() void
        +estaActiva() boolean
    }
    Reserva --> Sala : reserva
    Reserva --> Empleado : solicitada por

Esqueletos

package com.nexussoftware.bibliotech.dominio;

public class Sala {
    String nombre;
    int capacidadMaxima;
    boolean tieneProyector;

    // Operaciones previstas:
    //   admite(int asistentes) -> boolean
}
package com.nexussoftware.bibliotech.dominio;

public class Reserva {
    Sala sala;                 // referencia a otro objeto: asociacion
    Empleado solicitante;      // asociacion
    int horaInicio;            // 9 = 09:00, formato entero provisional
    int horaFin;
    int asistentes;
    boolean activa;

    // Operaciones previstas:
    //   cancelar()      -> void
    //   estaActiva()    -> boolean
    //   cabenTodos()    -> boolean  (delega en sala.admite(asistentes))
}

Dos detalles que reaparecerán: los campos que referencian a otras clases (Sala sala) son exactamente lo que dibujábamos como flecha en el diagrama, y las horas se modelan como enteros porque LocalTime pertenece a java.time, que se estudia en la lección 10-05.

Solución 3

(a) multaDelUltimoPrestamo en Libro está mal colocado. La multa es consecuencia de una operación de préstamo concreta, no una propiedad del libro. Con este diseño, si el mismo ejemplar se presta cinco veces, el campo solo recuerda la última multa y pierde el historial; y peor aún, obliga a Libro a conocer plazos y tarifas, que no son asunto suyo. La multa pertenece a Prestamo.

(b) nombreDelEmpleadoActual en Libro está mal por dos razones. Primera, es la misma dispersión que sufre hoy BiblioTechApp: guardar el nombre en lugar del Empleado deja el dato huérfano y sin posibilidad de acceder al identificador o a los préstamos acumulados. Segunda, y más importante, el vínculo libro–empleado solo existe mientras hay un préstamo, así que su lugar natural es la clase Prestamo, que ya relaciona ambos. Si Libro debe saber algo, es únicamente si está disponible o no.

(c) imprimirReciboDeDevolucion() mezcla dominio y presentación. Una clase de dominio no debería saber que existe una consola, ni el formato del recibo, ni el ancho de las columnas. Si mañana BiblioTech se convierte en aplicación web (módulo 12), habría que reescribir la clase entera. El recibo lo genera quien se ocupa de la interfaz. Es el problema de los niveles de abstracción mezclados, que se trata a fondo en la lección 03-08.

(d) guardarEnFichero() añade una responsabilidad ajena. Persistir en disco es un asunto de infraestructura (módulo 7), no del concepto "libro". Una clase con dos motivos distintos para cambiar —cambia el negocio, cambia el formato de fichero— es una clase que hará infelices a quienes la mantengan.

Diseño corregido, en esqueleto:

public class Libro {
    String titulo;
    String autor;
    String isbn;
    int anioPublicacion;
    boolean disponible;
    // Operaciones: estaDisponible(), prestar(), devolver()
}

public class Prestamo {
    Libro libro;              // que se presta
    Empleado empleado;        // a quien se presta
    int diasTranscurridos;
    // Operaciones: calcularDiasRetraso(), calcularMulta(), clasificarGravedad()
}

Conclusión

En esta lección has cambiado de forma de pensar antes de cambiar de forma de escribir. Has visto por qué el estilo procedimental se degrada cuando el programa crece —datos dispersos, estado global, reglas duplicadas, imposibilidad de escalar—, con tu propio BiblioTechApp como caso de estudio. Has aprendido el vocabulario esencial: clase como plano y objeto como ejemplar, identidad, estado y comportamiento, instancia y referencia. Tienes un mapa de los cuatro pilares y de la lección en la que se desarrolla cada uno. Y, sobre todo, has modelado el dominio de BiblioTech: de los sustantivos del enunciado a tres clases —Libro, Empleado, Prestamo— con responsabilidades explícitas, relaciones dibujadas y un diagrama objetivo que guiará el resto del módulo. También sabes que la POO no es gratis: cuesta indirección, ceremonia y riesgo de sobrediseño, y solo se paga sola cuando el software tiene que crecer.

Tienes el plano. En la lección siguiente, Clases y Objetos, empiezas a construir: declararás la clase Libro con su sintaxis exacta, verás qué valor toman los campos antes de asignarles nada, crearás objetos con new siguiendo paso a paso qué ocurre en la pila y en el heap, descubrirás qué significa de verdad un NullPointerException y por qué dos referencias al mismo objeto pueden provocar sorpresas desagradables. Al terminarla, "Java Efectivo", "Patrones de Diseño" y "Refactorización" habrán dejado de ser cadenas de texto sueltas para convertirse en tres objetos con vida propia dentro de BiblioTechApp.

Curso de Programación en Java

Módulo 1: Introducción a Java

Módulo 2: Flujo de Control

Módulo 3: Programación Orientada a Objetos

Módulo 4: Programación Orientada a Objetos Avanzada

Módulo 5: Estructuras de Datos y Colecciones

Módulo 6: Manejo de Excepciones

Módulo 7: Entrada/Salida de Archivos

Módulo 8: Multihilo y Concurrencia

Módulo 9: Redes

Módulo 10: Temas Avanzados

Módulo 11: Frameworks y Librerías de Java

Módulo 12: Construcción de Aplicaciones del Mundo Real

© Copyright 2026. Todos los derechos reservados