Menu
Coddy logo textTech

Lógica de validación

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

Hasta ahora, hemos explorado diferentes formas de proteger los datos: las convenciones de nomenclatura señalan la intención, los cierres (closures) ocultan las variables por completo y las tablas de solo lectura evitan todas las modificaciones. Pero a menudo se necesita algo intermedio: permitir cambios, pero solo los válidos.

Aquí es donde los métodos setter se vuelven poderosos. En lugar de simplemente asignar un valor, un setter puede comprobar si el nuevo valor tiene sentido antes de aceptarlo:

local Person = {}
Person.__index = Person

function Person:new(name, age)
    local obj = {
        _name = name,
        _age = age
    }
    setmetatable(obj, Person)
    return obj
end

function Person:setAge(newAge)
    if newAge < 0 then
        print("Error: Age cannot be negative")
        return
    end
    self._age = newAge
end

Cuando alguien llama a person:setAge(-5), el método captura la entrada no válida y se niega a actualizar. El estado del objeto permanece consistente. Sin esta protección, los datos erróneos podrían corromper silenciosamente tu programa; imagina calcular los beneficios de jubilación con una edad negativa.

La validación puede ser tan simple o compleja como sea necesario. Podrías comprobar rangos, verificar tipos o asegurarte de que los valores coincidan con los formatos esperados. El principio clave es que el setter actúa como un guardián, asegurando que solo entren datos coherentes en tu objeto.

challenge icon

Desafío

Fácil

¡Vamos a construir una clase Player que proteja sus atributos de salud y nivel utilizando lógica de validación en los métodos setter! Esto asegura que los personajes del juego nunca terminen con estadísticas imposibles.

Organizarás tu código en dos archivos:

  • Player.lua: Crea una clase que gestione las estadísticas de un jugador con la validación adecuada. El constructor :new(name) debe inicializar al jugador con un nombre, _health establecido en 100, y _level establecido en 1. Incluye estos métodos:
    • :getName() — devuelve el nombre del jugador
    • :getHealth() — devuelve la salud actual
    • :getLevel() — devuelve el nivel actual
    • :setHealth(value) — actualiza la salud solo si el valor está entre 0 y 100 (inclusive). Si no es válido, imprime Error: Health must be between 0 and 100 y no cambies el valor.
    • :setLevel(value) — actualiza el nivel solo si el valor es 1 o mayor. Si no es válido, imprime Error: Level must be at least 1 y no cambies el valor.
  • main.lua: Requiere tu módulo Player y lee un nombre de jugador, luego dos valores para probar los setters. Crea un jugador, intenta establecer su salud al primer valor, intenta establecer su nivel al segundo valor, luego imprime las estadísticas finales del jugador.

Recibirás tres entradas:

  1. El nombre del jugador
  2. Un valor de salud para intentar establecer (un número, podría ser válido o inválido)
  3. Un valor de nivel para intentar establecer (un número, podría ser válido o inválido)

Tu salida debe mostrar cualquier mensaje de error de los intentos inválidos, seguido de las estadísticas finales del jugador:

Name: {name}
Health: {finalHealth}
Level: {finalLevel}

Por ejemplo, si las entradas son Hero, -20, y 5, la salida debería ser:

Error: Health must be between 0 and 100
Name: Hero
Health: 100
Level: 5

El setter de salud rechazó -20 (manteniendo la salud en 100), mientras que el setter de nivel aceptó 5 como válido.

Si las entradas son Warrior, 75, y 0, la salida debería ser:

Error: Level must be at least 1
Name: Warrior
Health: 75
Level: 1

Hoja de referencia

Los métodos setter le permiten validar datos antes de actualizar las propiedades del objeto, asegurando que solo se acepten valores válidos.

Un setter básico con validación:

function Person:setAge(newAge)
    if newAge < 0 then
        print("Error: Age cannot be negative")
        return
    end
    self._age = newAge
end

El setter actúa como un guardián: comprueba si el nuevo valor es válido antes de actualizar la propiedad interna. Si la validación falla, imprime un error y finaliza la ejecución prematuramente sin modificar los datos.

La validación puede incluir:

  • Comprobaciones de rango (por ejemplo, age >= 0)
  • Límites de frontera (por ejemplo, 0 <= health <= 100)
  • Verificación de tipo
  • Validación de formato

Esto evita que los datos no válidos corrompan el estado de su objeto y mantiene la consistencia de su programa.

Pruébalo tú mismo

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

-- Leer entradas
local name = io.read()
local healthValue = tonumber(io.read())
local levelValue = tonumber(io.read())

-- TODO: Crear un nuevo jugador con el nombre dado

-- TODO: Intentar establecer la salud del jugador a healthValue

-- TODO: Intentar establecer el nivel del jugador a levelValue

-- TODO: Imprimir las estadísticas finales del jugador en el formato:
-- Name: {name}
-- Health: {finalHealth}
-- Level: {finalLevel}
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