Llamar a métodos del padre
Parte de la sección Object Oriented Programming del Journey de Lua de Coddy — lección 38 de 70.
A veces, sobrescribir un método por completo no es lo que deseas. En su lugar, es posible que desees extender el comportamiento del padre: hacer lo que hace el padre y luego añadir algo extra. Para lograr esto, puedes llamar al método del padre directamente desde la sobrescritura del hijo.
La técnica utiliza la sintaxis de punto con el nombre de la clase padre, pasando explícitamente self como el primer argumento:
local Animal = {}
Animal.__index = Animal
function Animal:new(name)
local obj = {name = name}
setmetatable(obj, Animal)
return obj
end
function Animal:speak()
print(self.name .. " makes a sound")
end
-- Dog extiende el comportamiento del padre
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
function Dog:new(name)
local obj = Animal.new(Animal, name)
setmetatable(obj, Dog)
return obj
end
function Dog:speak()
Animal.speak(self) -- Llama primero al método del padre
print(self.name .. " wags tail happily")
endLa línea clave es Animal.speak(self). Al usar la sintaxis de punto en la clase padre y pasar self manualmente, invocamos el método original antes de añadir nuestro propio comportamiento:
local buddy = Dog:new("Buddy")
buddy:speak()
-- Salida:
-- Buddy hace un sonido
-- Buddy menea la cola alegrementeEste patrón es útil cuando el método padre realiza un trabajo importante que no quieres duplicar. El hijo puede ejecutar la lógica del padre primero, al final o incluso en medio de su propio código, lo que te da un control total sobre cómo se combinan los comportamientos.
Desafío
Fácil¡Vamos a construir un sistema de saludo donde un FormalPerson extiende el comportamiento de una Person regular! En lugar de reemplazar completamente cómo se presenta una persona, la versión formal primero hará la presentación estándar y luego añadirá un toque extra de cortesía.
Organizarás tu código en tres archivos:
Person.lua: Tu clase base con un constructor:new(name)que almacena el nombre de la persona. Incluye un método:introduce()que imprime el nombre de la persona seguido desays hi. Este es el comportamiento base que será extendido.FormalPerson.lua: Una clase hija que hereda de Person. Su constructor debe llamar al constructor del padre para manejar el nombre. Sobrescribe el método:introduce(), pero en lugar de reemplazar el comportamiento del padre por completo, llama primero al método del padre usandoPerson.introduce(self), luego imprime una línea adicional con el nombre de la persona seguido debows politely.main.lua: Requiere tu módulo FormalPerson, lee un nombre de la entrada, crea una instancia de FormalPerson y llama a:introduce()para ver ambos comportamientos combinados.
Recibirás una entrada: el nombre de la persona.
Cuando llames a :introduce() en un FormalPerson, debería producir dos líneas de salida: la primera del método del padre y la segunda de la adición del hijo:
{name} says hi
{name} bows politelyPor ejemplo, si la entrada es Eleanor, la salida debería ser:
Eleanor says hi
Eleanor bows politelyLa clave aquí es que FormalPerson no duplica la lógica de "says hi"; delega ese trabajo al método del padre y luego añade su propio comportamiento único encima. ¡Esto mantiene tu código limpio y demuestra cómo las clases hijas pueden extender en lugar de reemplazar la funcionalidad del padre!
Hoja de referencia
Para extender el comportamiento de un método padre en lugar de sobrescribirlo por completo, llama al método padre desde la sobrescritura del hijo usando la sintaxis de punto y pasando explícitamente self:
function ChildClass:method()
ParentClass.method(self) -- Llamar al método padre
-- Añadir comportamiento adicional
endEjemplo completo que muestra la extensión de métodos:
local Animal = {}
Animal.__index = Animal
function Animal:new(name)
local obj = {name = name}
setmetatable(obj, Animal)
return obj
end
function Animal:speak()
print(self.name .. " makes a sound")
end
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
function Dog:new(name)
local obj = Animal.new(Animal, name)
setmetatable(obj, Dog)
return obj
end
function Dog:speak()
Animal.speak(self) -- Ejecutar primero el comportamiento del padre
print(self.name .. " wags tail happily") -- Añadir comportamiento del hijo
end
local buddy = Dog:new("Buddy")
buddy:speak()
-- Salida:
-- Buddy makes a sound
-- Buddy wags tail happilyEl método padre se puede llamar en cualquier punto: antes, después o en medio de la propia lógica del hijo, lo que otorga un control total sobre cómo se combinan los comportamientos.
Pruébalo tú mismo
-- main.lua: Punto de entrada para el sistema de saludos
local FormalPerson = require('FormalPerson')
-- Leer el nombre de la persona desde la entrada
local name = io.read()
-- TODO: Crear una instancia de FormalPerson con el nombre dado
-- TODO: Llamar al método introduce en la instancia de FormalPerson
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ósito7Polimorfismo y Sobrescritura
Sobrescritura de métodosLlamar a métodos del padreDuck TypingInterfaz comúnComprobación de tiposRepaso - Roles de empleados2Patró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