1. El Filtro Mental: "Es un" vs "Tiene un"
La herencia (extends) genera el acoplamiento más fuerte en POO. Si la relación no pasa la prueba estricta "X es un Y", NUNCA se hereda: se compone mediante un campo privado ("X tiene un Y").
// Herencia limpia: Auto ES UN Vehículo
public class Auto extends Vehiculo {
private Motor motor; // Composición interna
} 2. El Heap en Capas y el Encadenamiento con super()
Al hacer new Auto("Toyota"), NO se crean dos objetos en memoria. Se crea un ÚNICO bloque en el Heap organizado en capas. Por contrato de la JVM, la superclase se construye primero mediante super() antes de que corra el código de la subclase.
public Auto(String marca) {
super(marca); // <-- ¡Debe ser la 1ra sentencia!
this.baulAbierto = false;
} 3. Sobrecarga vs Sobrescritura: Compilación vs Runtime
Sobrecarga (Overload): misma clase, mismo nombre, parámetros diferentes; resuelto estáticamente por javac. Sobrescritura (Override): herencia, misma firma; resuelto en caliente por la JVM según el objeto real.
// El compilador verifica que la firma coincida
@Override
public void arrancar() {
System.out.println("Auto arrancando con llave codificada");
} 4. Despacho Dinámico y la Tabla de Métodos Virtuales (vtable)
Con `Vehiculo v = new Auto()`, el compilador valida el tipo estático (Vehiculo). Pero al invocar `v.arrancar()`, la JVM consulta en runtime la vtable del objeto concreto en el Heap y salta directamente al código de Auto.
Vehiculo v = new Auto("Toyota");
v.arrancar(); // JVM consulta vtable -> Auto.arrancar() 5. Arrays Polimórficos y Pattern Matching
Un array heterogéneo `Vehiculo[]` permite manipular distintos objetos de manera uniforme sin usar switch ni condicionales. Para acceder a métodos exclusivos de una subclase, Java 16+ ofrece Pattern Matching para instanceof.
for (Vehiculo v : flota) {
v.arrancar(); // Polimorfismo puro
// Java 16+ Pattern Matching (sin cast manual):
if (v instanceof Auto a) {
a.abrirBaul();
}
}