Llamar a métodos del padre
Parte de la sección Programación Orientada a Objetos del Journey de Lua de Coddy. Lección 38 de 70.
A veces, reemplazar por completo un método no es lo que quieres. En su lugar, es posible que quieras extender el comportamiento del padre: hacer lo que hace el padre y después añadir algo extra. Para lograrlo, puedes llamar directamente al método del padre desde la sobrescritura del hijo.
La técnica utiliza la sintaxis de punto con el nombre de la clase principal, pasando explícitamente self como 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 al método del padre primero
print(self.name .. " wags tail happily")
endLa línea clave es Animal.speak(self). Al usar la sintaxis de punto en la clase principal 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 mueve la cola felizmenteEste patrón es útil cuando el método de la clase padre realiza un trabajo importante que no quieres duplicar. La clase hija puede ejecutar primero la lógica de la clase padre, al final o incluso en medio de su propio código, lo que te brinda un control total sobre cómo se combinan los comportamientos.
Desafío
Fácil¡Construyamos un sistema de saludos donde una FormalPerson extienda el comportamiento de una Person normal! En lugar de reemplazar por completo la forma en que una persona se presenta, la versión formal hará primero la presentación estándar y después 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 se extenderá.FormalPerson.lua: Una clase hija que hereda de Person. Su constructor debe llamar al constructor principal para encargarse del nombre. Sobrescribe el método:introduce(), pero en lugar de reemplazar por completo el comportamiento de la clase principal, llama primero al método de la clase principal usandoPerson.introduce(self); después, 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 una FormalPerson, debe producir dos líneas de salida: la primera del método de la clase principal y la segunda de la adición de la clase hija:
{name} says hi
{name} bows politelyPor ejemplo, si la entrada es Eleanor, la salida debería ser:
Eleanor says hi
Eleanor bows politelyLa idea clave aquí es que FormalPerson no duplica la lógica de «says hi». Delega ese trabajo al método de la clase principal y después añade su propio comportamiento único. ¡Esto mantiene tu código limpio y demuestra cómo las clases hijas pueden extender la funcionalidad de la clase principal en lugar de reemplazarla!
Pruébalo tú mismo
-- main.lua: Punto de entrada para el sistema de saludos
local FormalPerson = require('FormalPerson')
-- Lee el nombre de la persona desde la entrada
local name = io.read()
-- TODO: Crea una instancia de FormalPerson con el nombre dado
-- TODO: Llama 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 Programación Orientada a Objetos
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 formasPractica por tu cuenta: Compilador de Lua online