Clases mediante metatablas
Simule clases utilizando tablas y __index para buscar métodos.
Clases mediante metatablas es una lección gratuita de Lua Academy en CoddyKit. Esta es la lección 1 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.
Patrón de tabla de clase
En Lua, una «clase» no es más que una tabla que almacena métodos. Las instancias son tablas cuya metatabla tiene __index apuntando a la tabla de la clase. Esto permite acceder a todos los métodos desde las instancias mediante la cadena de búsqueda.
local Animal = {}
Animal.__index = Animal
function Animal.new(name, sound)
return setmetatable({name=name, sound=sound}, Animal)
end
function Animal:speak()
print(self.name .. " says " .. self.sound)
end
local dog = Animal.new("Rex","Woof")
dog:speak() -- Rex says Woof__index apunta a la clase
Establecer ClassName.__index = ClassName significa «buscar las claves que falten en la tabla de la clase». Cuando se llama a un método de instancia, Lua no lo encuentra en la instancia, comprueba la metatabla (__index), encuentra la clase y busca allí el método.
local Point = {}
Point.__index = Point
Point.type = "2D Point"
function Point.new(x,y)
return setmetatable({x=x,y=y}, Point)
end
function Point:magnitude()
return math.sqrt(self.x^2 + self.y^2)
end
local p = Point.new(3,4)
print(p:magnitude()) -- 5.0
print(p.type) -- 2D Point (from class)Patrón de constructor
La función new() es el constructor: crea una tabla con los datos de la instancia y la devuelve envuelta en una metatabla que apunta a la clase. Esta es la forma estándar de crear objetos en Lua.
local Circle = {}
Circle.__index = Circle
function Circle.new(cx, cy, radius)
assert(radius > 0, "radius must be positive")
return setmetatable({cx=cx, cy=cy, r=radius}, Circle)
end
function Circle:area()
return math.pi * self.r^2
end
function Circle:perimeter()
return 2 * math.pi * self.r
end
local c = Circle.new(0, 0, 5)
print(string.format("Area: %.2f", c:area()))Sintaxis de métodos frente a funciones
obj:method() es una forma abreviada de obj.method(obj). Defina los métodos con sintaxis de dos puntos (function Cls:method()) para obtener self de forma implícita. Llámelos con dos puntos para pasar la instancia. Mezclar puntos y dos puntos provoca errores sutiles.
local Dog = {}
Dog.__index = Dog
-- Define with colon: self is implicit
function Dog:bark(times)
for i = 1, (times or 1) do
print(self.name .. ": Woof!")
end
end
function Dog.new(name)
return setmetatable({name=name}, Dog)
end
local d = Dog.new("Buddy")
d:bark(2) -- Buddy: Woof! (x2)
-- Dog.bark(d,1) -- same thing, explicit selfCampos de clase frente a campos de instancia
Los campos de la tabla de la clase se comparten entre todas las instancias (variables de clase). Los campos de la tabla de la instancia son propios de cada instancia. Una instancia puede ocultar un campo de la clase creando su propio campo con el mismo nombre.
local Entity = {}
Entity.__index = Entity
Entity.count = 0 -- class-level counter
function Entity.new(name)
Entity.count = Entity.count + 1
return setmetatable({name=name, id=Entity.count}, Entity)
end
local a = Entity.new("alpha")
local b = Entity.new("beta")
local c = Entity.new("gamma")
print(Entity.count) -- 3
print(a.id, b.id, c.id) -- 1 2 3tostring para clases
Añada __tostring a la tabla de la clase para obtener una salida de impresión legible. Como la metatabla de la instancia es la clase, y la clase tiene __tostring, todas las instancias lo usarán automáticamente.
local Vec2 = {}
Vec2.__index = Vec2
Vec2.__tostring = function(v)
return string.format("Vec2(%g, %g)", v.x, v.y)
end
function Vec2.new(x,y)
return setmetatable({x=x,y=y}, Vec2)
end
function Vec2.__add(a, b)
return Vec2.new(a.x+b.x, a.y+b.y)
end
local v1 = Vec2.new(1,2)
local v2 = Vec2.new(3,4)
print(v1+v2) -- Vec2(4, 6)Comprobar el tipo de una instancia
Compruebe si un objeto es una instancia de una clase comparando su metatabla con la tabla de la clase. Este es el equivalente de instanceof en Lua.
local Dog = {}
Dog.__index = Dog
function Dog.new(name)
return setmetatable({name=name}, Dog)
end
local function isDog(obj)
return getmetatable(obj) == Dog
end
local d = Dog.new("Rex")
local t = {}
print(isDog(d)) -- true
print(isDog(t)) -- falseMétodos privados
Los métodos privados son funciones locales del archivo del módulo. No se pueden llamar desde fuera, pero están disponibles dentro de los métodos públicos del módulo como upvalues.
local Account = {}
Account.__index = Account
-- Private helper
local function validate(amount)
return type(amount)=="number" and amount > 0
end
function Account.new(balance)
return setmetatable({balance=balance or 0}, Account)
end
function Account:deposit(amount)
assert(validate(amount), "invalid amount")
self.balance = self.balance + amount
end
function Account:getBalance() return self.balance endComparación de clases
Sobrecargue __eq y __lt para personalizar la igualdad y el orden. Lua solo llama a __eq para tablas cuando ambos operandos comparten la misma metatabla.
local Temp = {}
Temp.__index = Temp
Temp.__eq = function(a,b) return a.celsius == b.celsius end
Temp.__lt = function(a,b) return a.celsius < b.celsius end
Temp.__tostring = function(t)
return t.celsius.."°C"
end
function Temp.new(c)
return setmetatable({celsius=c}, Temp)
end
local t1 = Temp.new(100)
local t2 = Temp.new(0)
print(t1 == Temp.new(100)) -- true
print(t2 < t1) -- trueVarias clases
Cada clase es una tabla independiente con su propia metatabla. Los objetos de clases diferentes tienen metatablas diferentes. Esta es la base de un sistema de POO con varias clases en Lua.
local Cat = {}
Cat.__index = Cat
function Cat.new(name) return setmetatable({name=name,lives=9},Cat) end
function Cat:loseLife() self.lives=self.lives-1; return self.lives end
local Dog2 = {}
Dog2.__index = Dog2
function Dog2.new(name) return setmetatable({name=name,tricks={}},Dog2) end
function Dog2:learn(t) self.tricks[#self.tricks+1]=t end
local c = Cat.new("Whiskers")
local d = Dog2.new("Buddy")
d:learn("sit"); d:learn("stay")
print(c:loseLife(), #d.tricks) -- 8 2Comprobación rápida
¿Por qué se establece ClassName.__index = ClassName?
Resumen: clases mediante metatablas
Resumen:
- Clase = tabla +
__index = self - Constructor:
function Cls.new(...) return setmetatable({}, Cls) end - Métodos: se definen en la tabla de la clase y se llaman con sintaxis de dos puntos
- Campos de clase frente a campos de instancia: los campos de clase se comparten y los de instancia son propios de cada objeto
- Comprobación de tipo:
getmetatable(obj) == Cls
Preguntas frecuentes
¿La lección «Clases mediante metatablas» es gratis?
Sí — el texto completo de «Clases mediante metatablas» 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 «Clases mediante metatablas»?
Simule clases utilizando tablas y __index para buscar métodos. 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 1 de 4.
¿Cuánto tiempo toma la lección «Clases mediante metatablas»?
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
- Clases mediante metatablas
- Constructores y new()
- Métodos de instancia y self
- Encapsulación con closures