1. Clase Abstracta: El Molde Incompleto en Memoria
Una clase abstracta representa un concepto que no puede existir por sí mismo en el mundo real (ej. "Figura"). El compilador prohíbe taxativamente hacer new Figura(); solo sus subclases concretas completas pueden nacer en el Heap.
public abstract class Figura {
private String color;
public abstract double calcularArea(); // Sin cuerpo
} 2. Interfaces: El Enchufe y Contrato Universal
Una interfaz es un puerto estándar que desacopla por completo quién consume un servicio de cómo se implementa. El cliente solo habla con la interfaz Exportable sin saber si los bytes van a PDF, Excel o JSON.
public void procesar(Exportable exp) {
byte[] datos = exp.exportar(); // Desacople total
} 3. Métodos default y la Resolución del Diamante
Java 8 incorporó métodos default para evolucionar interfaces sin romper implementaciones existentes. Si una clase implementa dos interfaces que definen el mismo método default, el compilador exige resolver la colisión explícitamente.
@Override
public void imprimir() {
ImpresoraA.super.imprimir(); // Desambiguación explícita
} 4. Herencia vs Implementación: is-a frente a can-do
Una clase solo puede extender una superclase ("is-a", identidad y estado compartido), pero puede implementar infinitas interfaces ("can-do", habilidades ortogonales).
public class Pato extends Ave
implements Volador, Nadador {
// Hereda estado de Ave
// Cumple contratos de Volador y Nadador
} 5. Namespaces y Paquetes: Evitar Colisiones
Los paquetes en Java estructuran el código y resuelven colisiones de nombres mediante el FQCN (Fully Qualified Class Name). Dos clases llamadas Item pueden coexistir si pertenecen a paquetes distintos.
// package-private: solo visible para el paquete
class ValidadorInterno {
void validar() { ... }
} 6. Modelado: Asociación, Agregación y Composición
No todo es herencia. El acoplamiento entre objetos se gradúa según la dependencia de su ciclo de vida en el Heap: Asociación (débil), Agregación (compartido) y Composición (fuerte, muerte en cascada).
// Composición: la Factura crea y posee sus items
public class Factura {
private final Item[] items;
} 7. Desafío: Simulador Polimórfico de Medios de Pago
Ejecución polimórfica en acción: una clase abstracta MedioPago define procesarPago(monto) y una interfaz Reembolsable agrega la capacidad reembolsar(). Probá cada medio y verificá cómo reacciona el sistema.
public void procesar(MedioPago m, double monto) {
m.procesarPago(monto); // Abstracto
if (m instanceof Reembolsable r) {
r.emitirComprobante();
}
}