Sobrescritura de métodos
Parte de la sección Object Oriented Programming del Journey de Lua de Coddy — lección 37 de 70.
Hasta ahora, las clases hijas han heredado los métodos de la clase padre y han añadido otros nuevos. ¿Pero qué pasa si una clase hija necesita el mismo nombre de método con un comportamiento diferente? Esto se conoce como sobrescritura de métodos (method overriding).
Cuando defines un método en una clase hija con el mismo nombre que uno en la clase padre, la versión de la hija tiene prioridad. La cadena de búsqueda de Lua comprueba primero la clase hija; si encuentra el método allí, deja de buscar.
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 sobrescribe speak()
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()
print(self.name .. " barks: Woof!")
endAhora cada clase responde de manera diferente a la misma llamada de método:
local generic = Animal:new("Creature")
local buddy = Dog:new("Buddy")
generic:speak() -- Salida: Creature hace un sonido
buddy:speak() -- Salida: Buddy ladra: ¡Guau!El :speak() de Dog reemplaza completamente la versión del padre para las instancias de Dog. Esto te permite crear un comportamiento especializado mientras mantienes una interfaz consistente: cada animal puede :speak(), pero cada especie lo hace de manera diferente.
Desafío
Fácil¡Vamos a construir un pequeño reino animal donde diferentes criaturas hablan a su manera única! Crearás una clase base Animal y dos clases hijas—Cat y Cow—que sobrescribirán el método :speak() del padre con su propio comportamiento especializado.
Organizarás tu código en cuatro archivos:
Animal.lua: Tu clase base con un constructor:new(name)que almacena el nombre del animal. Incluye un método:speak()que imprima el nombre del animal seguido demakes a sound. Este es el comportamiento por defecto que las clases hijas sobrescribirán.Cat.lua: Una clase hija que hereda de Animal. Su constructor:new(name)debe llamar al constructor del padre y luego volver a vincular la metatabla a Cat. Sobrescribe el método:speak()para que los gatos digan algo diferente—imprime el nombre del gato seguido demeows: Meow!Cow.lua: Otra clase hija que hereda de Animal. Configura el constructor de la misma manera que Cat. Sobrescribe:speak()para que las vacas impriman su nombre seguido demoos: Moo!main.lua: ¡Une todo! Lee dos nombres de la entrada, crea un Cat con el primer nombre y un Cow con el segundo nombre, luego llama a:speak()en cada uno para demostrar que el mismo nombre de método produce resultados diferentes según la clase.
Recibirás dos entradas:
- El nombre del gato
- El nombre de la vaca
En tu archivo principal, crea ambos animales y llama a :speak() primero en el gato y luego en la vaca.
Por ejemplo, si las entradas son Whiskers y Bessie, la salida debería ser:
Whiskers meows: Meow!
Bessie moos: Moo!Observa cómo ambos animales responden a la misma llamada al método :speak(), pero cada uno produce una salida específica para su tipo. La versión de Cat reemplaza completamente el comportamiento genérico "makes a sound" del padre, al igual que la de Cow. ¡Esto es la sobrescritura de métodos en acción—misma interfaz, diferentes implementaciones!
Hoja de referencia
La anulación de métodos permite que una clase hija defina un método con el mismo nombre que un método del padre, reemplazando el comportamiento del padre con una funcionalidad especializada.
Cuando Lua busca un método, primero comprueba la clase hija. Si encuentra el método allí, utiliza esa versión y deja de buscar en la clase padre.
Ejemplo básico de anulació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
-- Dog overrides speak()
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()
print(self.name .. " barks: Woof!")
endUso del método anulado:
local generic = Animal:new("Creature")
local buddy = Dog:new("Buddy")
generic:speak() -- Output: Creature makes a sound
buddy:speak() -- Output: Buddy barks: Woof!El método de la clase hija reemplaza completamente la versión del padre para las instancias de esa clase hija, permitiendo un comportamiento especializado mientras se mantiene una interfaz consistente en todas las clases.
Pruébalo tú mismo
-- main.lua: Unir todo
local Cat = require('Cat')
local Cow = require('Cow')
-- Leer entrada
local catName = io.read()
local cowName = io.read()
-- TODO: Crear un Cat con el primer nombre
-- TODO: Crear un Cow con el segundo nombre
-- TODO: Llamar a :speak() en el gato primero, luego en la vaca
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