Composición sobre Herencia y Patrón Mixins con Object.assign()
Aprende por qué la composición suele ser superior a jerarquías complejas de herencia y cómo inyectar habilidades modulares con Mixins y Object.assign().
El Problema de la Herencia Rígida
El famoso científico de la computación Joe Armstrong (creador de Erlang) resumió el problema de las jerarquías profundas de herencia con una frase célebre:
"El problema con los lenguajes orientados a objetos tradicionales es todo ese entorno implícito que arrastran consigo. Tú solo querías un plátano, pero terminaste con un gorila sosteniendo el plátano y toda la selva entera detrás."
Si creas una clase Ave con el método volar(), ¿qué haces cuando debes modelar un Pingüino o un Avestruz (aves que no vuelan)? ¿O un Murciélago (mamífero que sí vuela)? Forzar todo en un árbol de herencia genera código roto.
La Máxima: "Favorece la Composición sobre la Herencia"
La Composición cambia la pregunta fundamental:
- En lugar de preguntarte qué ES tu objeto (is-a: un pato es un ave).
- Pregúntate qué HACE tu objeto (can-do: este objeto sabe nadar, sabe volar y sabe emitir sonido).
Patrón Mixin en JavaScript con `Object.assign()`
Un Mixin es un objeto que encapsula una habilidad o comportamiento concreto. Puedes mezclar múltiples Mixins en cualquier clase o prototipo utilizando Object.assign(Destino, ...Orígenes):
const volador = { volar() { return "Volando por los cielos..."; } };
const nadador = { nadar() { return "Nadando bajo el agua..."; } };
// ¡Inyección horizontal de habilidades!
Object.assign(Pato.prototype, volador, nadador);
⚡ Creación de Personajes de Videojuego Modulares con Mixins
Ejecuta el código en el Sandbox y observa cómo los personajes componen habilidades sin jerarquías rígidas:
// 1. Catálogo de Habilidades Modulares (Mixins)
const conAtaqueEspada = {
atacarConEspada() {
return `⚔️ ${this.nombre} ataca con su espada causando 45 puntos de daño.`;
}
};
const conLanzamientoHechizo = {
lanzarFuego() {
return `🔥 ${this.nombre} lanza una bola de fuego mágica causando 80 puntos de daño.`;
}
};
const conCuracion = {
curarAliado(aliado) {
return `💚 ${this.nombre} cura las heridas de ${aliado.nombre} restaurando 50 HP.`;
}
};
const conSigilo = {
ocultarse() {
return `👥 ${this.nombre} se desvanece en las sombras haciéndose invisible.`;
}
};
// 2. Clase Base Sencilla
class Personaje {
constructor(nombre, nivel = 1) {
this.nombre = nombre;
this.nivel = nivel;
this.vida = 100;
}
describir() {
return `[Nivel ${this.nivel}] ${this.nombre} (HP: ${this.vida}/100)`;
}
}
// 3. Composición de Clases Especializadas con Object.assign
// Un Guerrero solo ataca con espada
class Guerrero extends Personaje {}
Object.assign(Guerrero.prototype, conAtaqueEspada);
// Un Mago lanza hechizos y cura
class MagoBlanco extends Personaje {}
Object.assign(MagoBlanco.prototype, conLanzamientoHechizo, conCuracion);
// Un Paladín es híbrido: Ataca con espada Y sabe curar
class Paladin extends Personaje {}
Object.assign(Paladin.prototype, conAtaqueEspada, conCuracion);
// Un Asesino ataca con espada y tiene sigilo
class Asesino extends Personaje {}
Object.assign(Asesino.prototype, conAtaqueEspada, conSigilo);
// ==========================================
// PRUEBA EN EL SANDBOX
// ==========================================
const aragorn = new Guerrero("Aragorn", 10);
const gandalf = new MagoBlanco("Gandalf", 20);
const uther = new Paladin("Uther", 15);
console.log("=== DESCRIPCIÓN DE HÉROES ===");
console.log(aragorn.describir());
console.log(gandalf.describir());
console.log(uther.describir());
console.log("\n=== COMBATE MODULAR (HABILIDADES COMPUESTAS) ===");
console.log(aragorn.atacarConEspada());
console.log(gandalf.lanzarFuego());
console.log(gandalf.curarAliado(aragorn));
// El Paladín disfruta de ambas habilidades sin duplicar código
console.log("\n=== HABILIDADES DEL PALADÍN HÍBRIDO ===");
console.log(uther.atacarConEspada());
console.log(uther.curarAliado(gandalf));
Mini-Quiz de Retención
Comprueba tu comprensión antes de pasar a la siguiente lección¿Por qué la regla arquitectónica "Favorece la composición sobre la herencia" es tan recomendada en JavaScript?
¿Tienes dudas con este tema?
Sócrates AI puede darte analogías y explicarte este código paso a paso.🚀 ¿Quieres dominar Manual de Programación Orientada a Objetos en JavaScript (POO) y crear proyectos reales?
Aprende arquitectura limpia, desarrollo web moderno, buenas prácticas y despliegue en producción con nuestro Bootcamp Fullstack Developer con mentorías en vivo.
🏛️ Autoría y Propiedad Intelectual: Obra educativa original de David Amador para Kilopolis Academia (Solucionáticos), estructurada sobre las especificaciones y estándares abiertos del W3C, el estándar vivo de WHATWG y la documentación oficial de código abierto. © Todos los derechos reservados.