Sobrescritura y polimorfismo
Sobrescriba métodos de la clase principal y consiga despacho polimórfico en tiempo de ejecución.
Sobrescritura y polimorfismo es una lección gratuita de Lua Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Lua Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Lua Academy incluye 4 lecciones en total.
Sobrescritura de métodos
Una clase hija sobrescribe un método de la clase padre definiendo un método con el mismo nombre. Cuando se llama desde una instancia hija, se ejecuta la versión de la hija. La versión del padre sigue estando disponible mediante Parent.method(self).
local Shape={} Shape.__index=Shape
function Shape:area() return 0 end
function Shape:describe() print(type(self).." area="..self:area()) end
local Circle={} Circle.__index=Circle
setmetatable(Circle,{__index=Shape})
function Circle.new(r) return setmetatable({r=r},Circle) end
function Circle:area() return math.pi*self.r^2 end
local Square={} Square.__index=Square
setmetatable(Square,{__index=Shape})
function Square.new(s) return setmetatable({s=s},Square) end
function Square:area() return self.s^2 end
Circle.new(5):describe()
Square.new(4):describe()Despacho polimórfico
El polimorfismo permite que distintos tipos de objetos respondan de forma diferente al mismo mensaje. Una función que acepta cualquier «forma» y llama a :area() funciona con cualquier tipo de forma; cada uno responde con su propia implementación.
local shapes={
Circle.new(3),
Square.new(4),
Circle.new(1),
}
local total=0
for _,shape in ipairs(shapes) do
total=total+shape:area()
end
print(string.format("Total area: %.2f",total))Tipado pato
Lua utiliza tipado pato: si un objeto tiene el método, funciona. No hace falta declarar una interfaz formal. Una función que llama a :speak() funciona con cualquier objeto que tenga un método speak, independientemente de su clase.
local function makeNoise(obj)
if type(obj.speak)=="function" then
obj:speak()
else
print("(silent)")
end
end
local Duck={speak=function(self) print("Quack!") end}
local Robot={speak=function(self) print("Beep boop!") end}
local Rock={}
makeNoise(Duck) -- Quack!
makeNoise(Robot) -- Beep boop!
makeNoise(Rock) -- (silent)Polimorfismo de operadores
Los metamétodos como __add permiten el polimorfismo de operadores. Distintos tipos pueden responder a + con su propia semántica siempre que definan __add.
local Vec2={} Vec2.__index=Vec2
Vec2.__add=function(a,b) return Vec2.new(a.x+b.x,a.y+b.y) end
Vec2.__tostring=function(v) return "("..v.x..","..v.y..")" end
function Vec2.new(x,y) return setmetatable({x=x,y=y},Vec2) end
local Color={} Color.__index=Color
Color.__add=function(a,b)
return Color.new(math.min(255,a.r+b.r),math.min(255,a.g+b.g),math.min(255,a.b+b.b))
end
function Color.new(r,g,b) return setmetatable({r=r,g=g,b=b},Color) end
print(tostring(Vec2.new(1,2)+Vec2.new(3,4))) -- (4,6)Patrón Visitor
El patrón Visitor separa las operaciones de los objetos. Una operación «visita» objetos de distintos tipos y llama al método adecuado según el tipo. Úselo para operaciones que deben variar según el tipo sin modificar los tipos.
local function printInfo(obj)
local mt = getmetatable(obj)
if mt == Circle then
print(string.format("Circle r=%.1f area=%.2f",obj.r,obj:area()))
elseif mt == Square then
print(string.format("Square s=%.1f area=%.2f",obj.s,obj:area()))
end
end
for _,s in ipairs({Circle.new(3),Square.new(4)}) do
printInfo(s)
endTabla de interfaz
Defina una interfaz como una tabla de nombres de métodos. Valide que un objeto implemente todos los métodos requeridos antes de usarlo de forma polimórfica.
local function implements(obj, interface)
for _, method in ipairs(interface) do
if type(obj[method]) ~= "function" then
return false, "missing: "..method
end
end
return true
end
local Drawable = {"draw","resize","move"}
local Widget = {
draw=function(self) print("draw "..self.type) end,
resize=function(self,w,h) self.w,self.h=w,h end,
move=function(self,x,y) self.x,self.y=x,y end,
type="button"
}
local ok,err = implements(Widget,Drawable)
print(ok,err) -- true nilComprobación de existencia de un método
Antes de llamar de forma polimórfica a un método opcional, compruebe si el objeto lo tiene. Esto permite capacidades opcionales sin exigir una clase base común.
local function maybeUpdate(obj, dt)
if type(obj.update)=="function" then
obj:update(dt)
end
end
local objects={
{x=0,y=0,update=function(self,dt) self.x=self.x+10*dt end},
{x=0,y=0}, -- no update
{x=0,y=0,update=function(self,dt) self.y=self.y+5*dt end},
}
for _,o in ipairs(objects) do maybeUpdate(o,1) end
for _,o in ipairs(objects) do print(o.x,o.y) endTabla de despacho basada en tipos
En lugar de encadenar condiciones if/elseif, use una tabla de despacho: asigne nombres de tipos a funciones controladoras. Este es el patrón de polimorfismo basado en tablas.
local handlers={
number = function(v) return "num:"..v end,
string = function(v) return "str:\"".."..v.."\"" end,
boolean = function(v) return "bool:"..(v and "T" or "F") end,
table = function(v) return "tbl:#"..tostring(#v) end,
}
local function describe(v)
local h=handlers[type(v)]
return h and h(v) or "unknown"
end
print(describe(42))
print(describe("hello"))
print(describe({1,2,3}))Retornos covariantes
Los métodos de las clases hijas pueden devolver tipos más específicos que los métodos de las clases padre (retorno covariante). Como Lua tiene tipado dinámico, esto resulta natural: la factoría de una clase hija devuelve una instancia hija, no solo una instancia padre.
local Base={} Base.__index=Base
function Base.new() return setmetatable({type="base"},Base) end
function Base:copy() return Base.new() end
local Child={} Child.__index=Child
setmetatable(Child,{__index=Base})
function Child.new(extra)
local self=setmetatable({type="child"},Child)
self.extra=extra; return self
end
function Child:copy() return Child.new(self.extra) end -- covariant
local c=Child.new("hello")
local c2=c:copy()
print(c2.extra,getmetatable(c2)==Child) -- hello trueResumen del polimorfismo
El polimorfismo en Lua en la práctica consiste en usar el mismo nombre de método con un comportamiento diferente según el tipo. Se consigue mediante OOP basada en metatablas, comprobaciones de tipado pato o tablas de despacho. No hace falta un sistema formal de interfaces, solo convenciones coherentes para los nombres de métodos.
-- Three ways to achieve polymorphism:
-- 1. Metatable inheritance + method override
-- 2. Duck typing: just call it if it exists
-- 3. Dispatch table: map type -> handler
local function area(shape)
-- Duck typing approach:
assert(type(shape.area)=="function","needs area()")
return shape:area()
end
print(area({area=function() return 16 end})) -- 16Pregunta sobre polimorfismo
¿Cómo funciona el polimorfismo en Lua?
Repaso: sobrescritura y polimorfismo
Sobrescriba los métodos de la clase padre redefiniéndolos en la clase hija. Lua resuelve las llamadas desde abajo hacia arriba mediante la cadena __index, lo que permite un despacho polimórfico natural en tiempo de ejecución.
Preguntas frecuentes
¿La lección «Sobrescritura y polimorfismo» es gratis?
Sí — el texto completo de «Sobrescritura y polimorfismo» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Lua Academy, actualiza a CoddyKit PRO. El curso de Lua Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Sobrescritura y polimorfismo»?
Sobrescriba métodos de la clase principal y consiga despacho polimórfico en tiempo de ejecución. Practicas Lua Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Lua Academy?
No se requiere experiencia previa. Lua Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.
¿Cuánto tiempo toma la lección «Sobrescritura y polimorfismo»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Lua Academy?
Sí. Cada lección de Lua Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Herencia simple con encadenamiento de __index
- Llamada a métodos de la clase principal con super
- Patrones mixin
- Sobrescritura y polimorfismo