Configuración de la herencia
Parte de la sección Object Oriented Programming del Journey de Lua de Coddy — lección 31 de 70.
Hasta ahora, has construido clases donde cada objeto busca métodos en una única tabla de prototipos. ¿Pero qué pasa si quieres que una clase se base en otra? Aquí es donde entra en juego la herencia: una clase hija puede acceder a todo lo de una clase padre mientras añade sus propias características.
La idea clave es que la propia tabla de una clase puede tener una metatabla. Cuando Lua no puede encontrar algo en la clase hija, busca en el __index de la metatabla de la hija, el cual apunta a la clase padre.
-- Clase padre
local Animal = {}
Animal.__index = Animal
function Animal:new()
local obj = {}
setmetatable(obj, Animal)
return obj
end
function Animal:breathe()
print("Breathing...")
endAhora aquí está la configuración de la herencia. Creamos una clase hija y configuramos su metatabla para que busque en el padre:
-- Clase hija
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})Esta única línea—setmetatable(Dog, {__index = Animal})—crea el vínculo de herencia. Cuando una instancia de Dog llama a un método que no se encuentra en Dog, Lua consulta Animal.
La cadena de búsqueda funciona así: instance → Dog → Animal. Cada paso utiliza __index para encontrar la siguiente tabla en la que buscar. Esto permite que las clases hijas hereden automáticamente todos los métodos del padre sin tener que copiarlos.
Desafío
Fácil¡Vamos a construir tu primera jerarquía de herencia! Crearás una relación simple de clase padre-hijo donde una clase Machine sirve como base, y una clase Robot hereda de ella.
Organizarás tu código en tres archivos:
Machine.lua: Define tu clase padre con el patrón de clase estándar. Incluye un constructor:new()y un método:status()que imprimaMachine is operational. No olvides configurar__indexy devolver la clase al final del archivo.Robot.lua: Define tu clase hija que hereda de Machine. Requiere el módulo Machine, configura la tabla Robot con su propio__index, y establece el enlace de herencia usandosetmetatable(Robot, {__index = Machine}). Incluye un constructor:new()que cree una instancia con Robot como su metatabla.main.lua: Reúne todo requiriendo tu módulo Robot, creando una instancia de Robot y llamando al método heredado:status().
El concepto clave aquí es que tu clase Robot no define :status() por sí misma; hereda este método de Machine a través de la cadena de metatablas. Cuando llamas a :status() en una instancia de Robot, Lua buscará primero en Robot, no lo encontrará, y luego seguirá el enlace __index hacia Machine donde descubrirá el método.
Tu salida debería ser:
Machine is operationalEsta única línea demuestra que la herencia está funcionando: ¡tu Robot accedió con éxito a un método definido solo en su clase padre!
Hoja de referencia
Para crear herencia en Lua, establezca la metatabla de una tabla de clase para que apunte a la clase padre usando __index:
-- Clase padre
local Animal = {}
Animal.__index = Animal
function Animal:new()
local obj = {}
setmetatable(obj, Animal)
return obj
end
function Animal:breathe()
print("Breathing...")
end
-- Clase hija
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})El vínculo de herencia se crea con setmetatable(Dog, {__index = Animal}). Esto permite que las instancias de Dog accedan a los métodos de Animal automáticamente.
La cadena de búsqueda sigue: instancia → Clase hija → Clase padre. Cada paso utiliza __index para encontrar la siguiente tabla en la que buscar.
Pruébalo tú mismo
-- main.lua: Reúne todo
-- TODO: Requerir el módulo Robot
-- TODO: Crear una instancia de Robot usando Robot:new()
-- TODO: Llamar al método heredado :status() en tu instancia de robot
-- Esto debería imprimir "Machine is operational"
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Object Oriented Programming
1El concepto de 'self'
Tablas con funciones'self' explícitoLa sintaxis de dos puntosPunto vs. dos puntosResumen - Punto en movimiento4Proyecto: Banco Digital
Configuración del proyectoMétodo de depósito2Patrón de prototipo de clase
El concepto de prototipoVinculación con __indexEl constructor :new()Inicialización de atributosInstancias independientesResumen - Fábrica de coches5Sobrecarga de operadores en POO
Sumar objetosRestar objetosConcatenar objetosComparar objetos (<, >)Resumen - Matemáticas de la billetera8Encapsulamiento
Convenciones de nomenclaturaClosures para privacidadAcceso mediante ClosuresTablas de solo lecturaLógica de validaciónResumen - Bóveda segura11Patrones de diseño (Lite)
Funciones FactoryTabla SingletonPatrón IteradorObserver (Listener)Resumen - Logger Factory3Estado y Comportamiento de los Objetos
Variables de InstanciaMétodos GetterMétodos SetterPropiedades CalculadasFormateo de StringsComprobaciones de IgualdadResumen - Calificación del Estudiante6Fundamentos de la herencia
Configuración de la herenciaHerencia de métodosExtender el constructorAñadir métodos hijosCompartido vs. ÚnicoResumen: Jerarquía de formas