Validation Logic
Part of the Object Oriented Programming section of Coddy's Lua journey — lesson 47 of 70.
So far, we've explored different ways to protect data—naming conventions signal intent, closures hide variables completely, and read-only tables prevent all modifications. But often you need something in between: allowing changes, but only valid ones.
This is where setter methods become powerful. Instead of just assigning a value, a setter can check whether the new value makes sense before accepting it:
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
endWhen someone calls person:setAge(-5), the method catches the invalid input and refuses to update. The object's state remains consistent. Without this protection, bad data could silently corrupt your program—imagine calculating retirement benefits with a negative age.
Validation can be as simple or complex as needed. You might check ranges, verify types, or ensure values match expected formats. The key principle is that the setter acts as a gatekeeper, ensuring only sensible data enters your object.
Challenge
EasyLet's build a Player class that protects its health and level attributes using validation logic in setter methods! This ensures that game characters can never end up with impossible stats.
You'll organize your code across two files:
Player.lua: Create a class that manages a player's stats with proper validation. The constructor:new(name)should initialize the player with a name,_healthset to100, and_levelset to1. Include these methods::getName()— returns the player's name:getHealth()— returns the current health:getLevel()— returns the current level:setHealth(value)— updates health only if the value is between 0 and 100 (inclusive). If invalid, printError: Health must be between 0 and 100and don't change the value.:setLevel(value)— updates level only if the value is 1 or greater. If invalid, printError: Level must be at least 1and don't change the value.
main.lua: Require your Player module and read a player name, then two values to test the setters. Create a player, attempt to set their health to the first value, attempt to set their level to the second value, then print the player's final stats.
You will receive three inputs:
- The player's name
- A health value to attempt setting (a number, could be valid or invalid)
- A level value to attempt setting (a number, could be valid or invalid)
Your output should show any error messages from invalid attempts, followed by the player's final stats:
Name: {name}
Health: {finalHealth}
Level: {finalLevel}For example, if the inputs are Hero, -20, and 5, the output should be:
Error: Health must be between 0 and 100
Name: Hero
Health: 100
Level: 5The health setter rejected -20 (keeping health at 100), while the level setter accepted 5 as valid.
If the inputs are Warrior, 75, and 0, the output should be:
Error: Level must be at least 1
Name: Warrior
Health: 75
Level: 1Cheat sheet
Setter methods allow you to validate data before updating object properties, ensuring only valid values are accepted.
A basic setter with validation:
function Person:setAge(newAge)
if newAge < 0 then
print("Error: Age cannot be negative")
return
end
self._age = newAge
endThe setter acts as a gatekeeper—it checks if the new value is valid before updating the internal property. If validation fails, it prints an error and returns early without modifying the data.
Validation can include:
- Range checks (e.g., age >= 0)
- Boundary limits (e.g., 0 <= health <= 100)
- Type verification
- Format validation
This prevents invalid data from corrupting your object's state and keeps your program consistent.
Try it yourself
-- Require the Player module
local Player = require('Player')
-- Read inputs
local name = io.read()
local healthValue = tonumber(io.read())
local levelValue = tonumber(io.read())
-- TODO: Create a new player with the given name
-- TODO: Attempt to set the player's health to healthValue
-- TODO: Attempt to set the player's level to levelValue
-- TODO: Print the player's final stats in the format:
-- Name: {name}
-- Health: {finalHealth}
-- Level: {finalLevel}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1The 'Self' Concept
Tables with FunctionsExplicit 'self'The Colon SyntaxDot vs ColonRecap - Moving Point4Project: Digital Bank
Project SetupDeposit Method7Polymorphism & Overriding
Overriding MethodsCalling Parent MethodsDuck TypingCommon InterfaceChecking TypeRecap - Employee Roles10Project: Shape Manager
Project SetupRectangle Class2Class Prototype Pattern
The Prototype ConceptLinking with __indexThe :new() ConstructorInitializing AttributesIndependent InstancesRecap - Car Factory5Operator Overloading in OOP
Adding ObjectsSubtracting ObjectsConcatenating ObjectsComparing Objects (<, >)Recap - Wallet Math8Encapsulation
Naming ConventionsClosures for PrivacyAccess via ClosuresRead-Only TablesValidation LogicRecap - Secure Vault11Design Patterns (Lite)
Factory FunctionsSingleton TableIterator PatternObserver (Listener)Recap - Logger Factory3Object State and Behavior
Instance VariablesGetter MethodsSetter MethodsCalculated PropertiesFormatting StringsEquality ChecksRecap - Student Grade6Inheritance Basics
The Inheritance SetupInheriting MethodsExtending the ConstructorAdding Child MethodsShared vs UniqueRecap - Shape Hierarchy