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
endCuando 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.
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,_healthestablecido en100, y_levelestablecido en1. 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, imprimeError: Health must be between 0 and 100y no cambies el valor.:setLevel(value)— actualiza el nivel solo si el valor es 1 o mayor. Si no es válido, imprimeError: Level must be at least 1y 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:
- El nombre del jugador
- Un valor de salud para intentar establecer (un número, podría ser válido o inválido)
- 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: 5El 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: 1Hoja 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
endEl 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}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Object Oriented Programming
1El concepto de 'self'
Tablas con funciones'self' explícitoLa sintaxis de dos puntosPunto vs. dos puntosResumen - Punto en movimiento4Proyecto: Banco Digital
Configuración del proyectoMétodo de depósito2Patrón de prototipo de clase
El concepto de prototipoVinculación con __indexEl constructor :new()Inicialización de atributosInstancias independientesResumen - Fábrica de coches5Sobrecarga de operadores en POO
Sumar objetosRestar objetosConcatenar objetosComparar objetos (<, >)Resumen - Matemáticas de la billetera8Encapsulamiento
Convenciones de nomenclaturaClosures para privacidadAcceso mediante ClosuresTablas de solo lecturaLógica de validaciónResumen - Bóveda segura11Patrones de diseño (Lite)
Funciones FactoryTabla SingletonPatrón IteradorObserver (Listener)Resumen - Logger Factory3Estado y Comportamiento de los Objetos
Variables de InstanciaMétodos GetterMétodos SetterPropiedades CalculadasFormateo de StringsComprobaciones de IgualdadResumen - Calificación del Estudiante6Fundamentos de la herencia
Configuración de la herenciaHerencia de métodosExtender el constructorAñadir métodos hijosCompartido vs. ÚnicoResumen: Jerarquía de formas