SLIDE 1 / 5

1. The Mental Filter: "Is a" vs "Has a"

Inheritance (extends) creates the strongest coupling in OOP. If the domain relationship fails the strict "X is a Y" test, NEVER inherit: compose via a private field ("X has a Y").

✓ Herencia Válida ("Es un") Vehiculo arrancar() | frenar() Auto Auto extends Vehiculo Regla: Todo Auto ES un Vehículo ✕ Anti-Patrón de Modelado Motor cilindrada, rpm ¿Auto extends Motor? ✕ ¡NO! Auto (Composición) private Motor motor; ◆ Solución: Auto TIENE un Motor
Relationship Tester
Conceptual Question: Is a Car a Vehicle?
Architectural Verdict: HERENCIA (extends)
Design Rationale: 100% valid Liskov substitution.
// Herencia limpia: Auto ES UN Vehículo
public class Auto extends Vehiculo {
  private Motor motor; // Composición interna
}

2. The Heap in Layers and super() Chaining

Executing new Auto("Toyota") does NOT instantiate two objects. It allocates a SINGLE block in the Heap with concentric state layers. The JVM enforces that super() initializes the superclass state before subclass code executes.

Objeto Único en Heap @0x7B20 new Auto("Toyota", true) Capa Externa: Auto baulAbierto = true Núcleo: Vehiculo (super) marca = "Toyota" velocidad = 0 Orden de Ejecución 1 new Auto("Toyota") Entrada al constructor Auto 2 super("Toyota") 1ra línea: cede control a Vehiculo 3 Núcleo Vehiculo Listo Atributos base inicializados 4 Cuerpo de Auto this.baulAbierto = true
Constructor Tracer
Current Phase: 1. Calling new Auto()
Mandatory JVM Rule: super() siempre se ejecuta primero
public Auto(String marca) {
  super(marca); // <-- ¡Debe ser la 1ra sentencia!
  this.baulAbierto = false;
}

3. Overload vs Override: Compile-Time vs Runtime

Overload: same class, same name, different parameters; resolved at compile-time by javac. Override: subclassing, identical signature; resolved dynamically at runtime by JVM according to the concrete instance.

Sobrecarga (Overload) void acelerar(int kmh) void acelerar(int kmh, boolean turbo) Ámbito: Misma clase Resuelto por: javac (Estático) Firma distinta; no requiere herencia. Sobrescritura (@Override) Vehiculo: void arrancar() Auto: @Override void arrancar() Ámbito: Subclase (Herencia) Resuelto por: JVM (Dinámico) Misma firma; reemplaza comportamiento base.
Danger Without @Override
Annotation: @Override presente
Compiler Diagnostic: ✓ Sobrescritura validada
Runtime Effect: Dynamic dispatch to subclass.
// El compilador verifica que la firma coincida
@Override
public void arrancar() {
  System.out.println("Auto arrancando con llave codificada");
}

4. Dynamic Method Dispatch and the vtable

With `Vehiculo v = new Auto()`, the compiler checks the static reference type (Vehiculo). But when calling `v.arrancar()`, the JVM looks up the vtable of the concrete Heap instance and jumps straight to Auto code.

Stack Vehiculo v (Tipo estático) @0x4000 → Heap @0x4000 new Auto("Toyota") Header / Klass Pointer: → Auto.class (vtable) Campos en memoria: marca: "Toyota" vtable: Punteros de Código toString() -> Object arrancar() → Auto.arrancar() ¡Ejecuta Auto en caliente!
Dispatch Simulator
Static Type (Compile-time): Vehiculo
Dynamic Type (Heap): Auto
vtable target resolved: Auto.arrancar()
Vehiculo v = new Auto("Toyota");
v.arrancar(); // JVM consulta vtable -> Auto.arrancar()

5. Polymorphic Arrays and Pattern Matching

A polymorphic `Vehicle[]` array handles different vehicles uniformly without switch or if-chains. When accessing subclass-specific methods, modern Java 16+ provides Pattern Matching for instanceof.

Vehiculo[] flota = { auto, moto, camion }; [0] Auto arrancar() abrirBaul() *exclusivo [1] Moto arrancar() hacerWheelie() *exclusivo [2] Camion arrancar() cargarRemolque() *exclusivo for (Vehiculo v : flota) { v.arrancar(); } ✓ Auto arrancando con llave codificada [Rummm suave] Pattern matching: if (v instanceof Auto a) -> a.abrirBaul();
Polymorphic Runner
Current Element: flota[0] -> Auto
Executed Behavior: Auto.arrancar()
for (Vehiculo v : flota) {
  v.arrancar(); // Polimorfismo puro

  // Java 16+ Pattern Matching (sin cast manual):
  if (v instanceof Auto a) {
    a.abrirBaul();
  }
}