1. Abstract Class: The Incomplete Blueprint in Memory
An abstract class models a concept that cannot exist on its own in the real world (e.g. "Shape"). The compiler forbids new Shape(); only complete concrete subclasses can be instantiated in the Heap.
public abstract class Figura {
private String color;
public abstract double calcularArea(); // Sin cuerpo
} 2. Interfaces: The Universal Socket and Contract
An interface is a standardized port that decouples the service caller from the underlying implementation. The caller interacts only with Exportable without knowing whether data flows to PDF, Excel, or JSON.
public void procesar(Exportable exp) {
byte[] datos = exp.exportar(); // Desacople total
} 3. default Methods and Diamond Problem Resolution
Java 8 added default methods to evolve interfaces without breaking contracts. If a class implements two interfaces declaring conflicting default methods, the compiler mandates an explicit override resolution.
@Override
public void imprimir() {
ImpresoraA.super.imprimir(); // Desambiguación explícita
} 4. Inheritance vs Implementation: is-a vs can-do
A class can only extend one superclass ("is-a", shared identity and state), but it can implement infinite interfaces ("can-do", orthogonal capabilities).
public class Pato extends Ave
implements Volador, Nadador {
// Hereda estado de Ave
// Cumple contratos de Volador y Nadador
} 5. Namespaces and Packages: Collision Avoidance
Packages provide code geography and prevent name clashes using FQCN (Fully Qualified Class Name). Two classes named Item can coexist cleanly across separate packages.
// package-private: solo visible para el paquete
class ValidadorInterno {
void validar() { ... }
} 6. Modeling: Association, Aggregation, and Composition
Not everything is inheritance. Coupling between objects depends on their lifecycle in the Heap: Association (weak), Aggregation (shared), and Composition (strong cascade death).
// Composición: la Factura crea y posee sus items
public class Factura {
private final Item[] items;
} 7. Challenge: Polymorphic Payment Simulator
Polymorphism in action: an abstract MedioPago class declares procesarPago(amount) and a Reembolsable interface exposes reembolsar(). Test each gateway to witness how the system reacts.
public void procesar(MedioPago m, double monto) {
m.procesarPago(monto); // Abstracto
if (m instanceof Reembolsable r) {
r.emitirComprobante();
}
}