Menu
Coddy logo textTech

El metamétodo __newindex

Parte de la sección Lógica y flujo de control del Journey de Lua de Coddy. Lección 19 de 54.

Has aprendido cómo __index controla lo que sucede cuando intentas leer una clave que no existe en una tabla. Ahora descubrirás su contraparte: __newindex, que controla lo que sucede cuando intentas añadir o modificar un par clave-valor.

El metamétodo __newindex se activa cada vez que intentas asignar un valor a una clave que no existe actualmente en la tabla. Esto te da el poder de interceptar y controlar las modificaciones antes de que ocurran.

Aquí tienes un ejemplo sencillo que evita que se añadan nuevas claves a una tabla:

local readOnly = {}
local meta = {
    __newindex = function(table, key, value)
        print("Cannot add key: " .. key)
    end
}

setmetatable(readOnly, meta)

readOnly.name = "Alice"  -- Salida: Cannot add key: name
print(readOnly.name)     -- Salida: nil

Cuando intentas establecer readOnly.name = "Alice", Lua ve que name no existe en la tabla. En lugar de añadirlo, Lua llama a la función __newindex con tres argumentos: la propia tabla, la clave que se está estableciendo y el valor que se está asignando.

En este ejemplo, la función simplemente imprime un mensaje y en realidad no almacena nada.

También puedes usar __newindex para validar datos antes de permitirlos en tu tabla:

local player = {}
local meta = {
    __newindex = function(t, key, value)
        if key == "health" and type(value) ~= "number" then
            print("Health must be a number!")
        else
            rawset(t, key, value)
        end
    end
}

setmetatable(player, meta)

player.health = "high"  -- Salida: Health must be a number!
player.health = 100     -- Permitido

Observe el uso de rawset() en el segundo ejemplo. Esta función omite la metatabla y establece directamente el valor en la tabla.

Sin ello, establecer el valor activaría __newindex de nuevo, creando un bucle infinito.

challenge icon

Desafío

Fácil
Escribe una función createValidatedTable que reciba key y value y devuelva una tabla que solo acepte valores de tipo string para claves nuevas.

Crea una tabla vacía y asígnale una metatabla con __newindex que valide el tipo del valor. Si alguien intenta añadir un valor que no sea una cadena, usa rawset() para almacenar la cadena "invalid" en su lugar. Para los valores de tipo cadena, almacénalos normalmente usando rawset().

Lógica:

  • Crea una tabla vacía
  • Crea una metatabla con __newindex que reciba la tabla, la clave y el valor
  • Dentro de __newindex, comprueba si el valor es una cadena usando type(value) == "string"
  • Si es una cadena, usa rawset(t, key, value) para almacenarla
  • Si no es una cadena, usa rawset(t, key, "invalid") para almacenar "invalid" en su lugar
  • Asigna la metatabla a la tabla usando setmetatable()
  • Usa rawset() para añadir el par clave-valor inicial a la tabla (omitiendo la metatabla)
  • Devuelve la tabla

Parámetros:

  • key (string): La clave inicial que se añadirá a la tabla
  • value (string): El valor inicial que se añadirá a la tabla

Devuelve: Una tabla con validación que solo acepta valores de tipo cadena y que contiene el par clave-valor inicial (tabla)

Pruébalo tú mismo

function createValidatedTable(key, value)
    -- Escribe el código aquí
end
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 Lógica y flujo de control

Practica por tu cuenta: Compilador de Lua online