Menu
Coddy logo textTech

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
end

When 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 icon

Challenge

Easy

Let'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, _health set to 100, and _level set to 1. 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, print Error: Health must be between 0 and 100 and don't change the value.
    • :setLevel(value) — updates level only if the value is 1 or greater. If invalid, print Error: Level must be at least 1 and 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:

  1. The player's name
  2. A health value to attempt setting (a number, could be valid or invalid)
  3. 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: 5

The 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: 1

Cheat 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
end

The 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}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming