Menu
Coddy logo textTech

Vinculación con __index

Parte de la sección Object Oriented Programming del Journey de Lua de Coddy — lección 7 de 70.

Tienes una tabla prototipo con propiedades y métodos, ¿pero cómo haces que un nuevo objeto realmente la use? La respuesta reside en el metamétodo __index.

Cuando accedes a una clave que no existe en una tabla, Lua normalmente devuelve nil. Sin embargo, si la tabla tiene una metatabla con un campo __index, Lua buscará allí en su lugar. Al configurar __index para que apunte a tu prototipo, cualquier clave que falte se encontrará automáticamente en el prototipo:

local Dog = {
    species = "Canis familiaris",
    legs = 4
}

function Dog:bark()
    print("Woof!")
end

-- Crear una instancia vacía
local myDog = {}

-- Enlazarlo al prototipo
setmetatable(myDog, { __index = Dog })

print(myDog.species)  -- Salida: Canis familiaris
myDog:bark()          -- Salida: Woof!

La tabla myDog está completamente vacía, sin embargo, acceder a myDog.species funciona. Cuando Lua no encuentra species en myDog, consulta el __index de la metatabla y lo encuentra en Dog.

Esta es la base de la programación orientada a objetos en Lua. La instancia puede tener sus propios datos únicos, mientras que el comportamiento compartido reside en el prototipo. En la siguiente lección, aprenderás cómo envolver este patrón en una función constructora limpia.

challenge icon

Desafío

Fácil

¡Ahora pongamos en práctica el metamétodo __index! Crearás un prototipo y vincularás una instancia a él, permitiendo que la instancia acceda a propiedades y métodos que no posee directamente.

Organizarás tu código en dos archivos:

  • Robot.lua: Define una tabla prototipo Robot con:
    • Un campo model establecido en "RX-100"
    • Un campo batteryLevel establecido en 100
    • Un método :status() que imprima el estado actual del robot
    Devuelve la tabla al final del archivo.
  • main.lua: Requiere el módulo Robot, luego crea una tabla de instancia vacía y vincúlala al prototipo Robot usando setmetatable con __index. Esto permite que tu instancia vacía acceda a todo lo del prototipo.

Recibirás una entrada: un nombre para asignar a tu instancia de robot.

Después de vincular la instancia al prototipo:

  1. Asigna el nombre de entrada al campo name de tu instancia (esto se vuelve único para la instancia)
  2. Llama al método :status() en tu instancia

Tu método :status() debe imprimir en este formato exacto:

[name] ([model]) - Battery: [batteryLevel]%

Por ejemplo, si la entrada es Sparky, la salida debería ser:

Sparky (RX-100) - Battery: 100%

Observa cómo la instancia tiene su propio name, pero accede a model y batteryLevel desde el prototipo a través del enlace __index.

Hoja de referencia

El metamétodo __index permite que los objetos hereden propiedades y métodos de una tabla prototipo.

Cuando accedes a una clave que no existe en una tabla, Lua comprueba si la tabla tiene una metatabla con un campo __index. Si es así, Lua busca la clave en la tabla especificada por __index.

Para vincular una instancia a un prototipo:

local Prototype = {
    property = "value"
}

function Prototype:method()
    print("Method called")
end

-- Create an instance
local instance = {}

-- Link to prototype using __index
setmetatable(instance, { __index = Prototype })

-- Access prototype properties and methods
print(instance.property)  -- Output: value
instance:method()         -- Output: Method called

La tabla de la instancia puede estar vacía y, aun así, puede acceder a todas las propiedades y métodos del prototipo. La instancia también puede tener sus propias propiedades únicas que anulan o extienden el prototipo.

Este patrón es la base de la programación orientada a objetos en Lua, donde las instancias comparten el comportamiento de un prototipo mientras mantienen sus propios datos únicos.

Pruébalo tú mismo

-- Leer entrada
local name = io.read()

-- Requerir el módulo Robot
local Robot = require('Robot')

-- TODO: Crear una tabla de instancia vacía

-- TODO: Vincular la instancia al prototipo Robot usando setmetatable con __index

-- TODO: Asignar el nombre de entrada al campo name de tu instancia

-- TODO: Llamar al método :status() en tu instancia
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Object Oriented Programming