0Pricing
Lua Academy · Lección

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 self

Campos 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  3

tostring 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))  -- false

Mé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 end

Comparació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)              -- true

Varias 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  2

Comprobació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

  1. Clases mediante metatablas
  2. Constructores y new()
  3. Métodos de instancia y self
  4. Encapsulación con closures
← Volver a Lua Academy