Menu
CoddyTech

验证逻辑

本课属于 Coddy Lua 学习旅程的“面向对象编程”单元。第 47 课,共 70 课。

到目前为止,我们探索了保护数据的不同方法:命名约定可以表明意图,闭包可以完全隐藏变量,而只读表可以阻止所有修改。但很多时候,你需要一种介于两者之间的方式:允许修改,但只允许进行有效的修改。

这就是 setter 方法发挥作用的地方。setter 不只是赋值,还可以在接受新值之前检查它是否合理:

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

当有人调用 person:setAge(-5) 时,方法会捕获无效输入并拒绝更新。对象的状态保持一致。如果没有这种保护,错误数据可能会悄无声息地破坏你的程序:想象一下,用负数年龄计算退休福利。

验证可以根据需要设计得简单或复杂。你可以检查范围、验证类型,或确保值符合预期格式。关键原则是,设置方法充当把关者,确保只有合理的数据才能进入对象。

challenge icon

挑战

简单

我们来编写一个 Player 类,通过 setter 方法中的验证逻辑保护角色的生命值和等级属性!这样可以确保游戏角色不会出现不可能的属性值。

你需要将代码分成两个文件:

  • Player.lua:创建一个类,用适当的验证逻辑管理玩家的属性。构造函数 :new(name) 应使用玩家姓名初始化玩家,将 _health 设为 100,将 _level 设为 1。包含以下方法:
    • :getName():返回玩家的姓名
    • :getHealth():返回当前生命值
    • :getLevel():返回当前等级
    • :setHealth(value):仅当值在 0 到 100 之间(含 0 和 100)时更新生命值。如果值无效,则打印 Error: Health must be between 0 and 100,并且不更改该值。
    • :setLevel(value):仅当值大于或等于 1 时更新等级。如果值无效,则打印 Error: Level must be at least 1,并且不更改该值。
  • main.lua:引入 Player 模块,读取玩家姓名,然后读取两个用于测试 setter 方法的值。创建一个玩家,尝试将生命值设为第一个值,再尝试将等级设为第二个值,然后打印玩家的最终属性。

你会收到三个输入:

  1. 玩家的姓名
  2. 尝试设置的生命值(一个数字,可能有效,也可能无效)
  3. 尝试设置的等级(一个数字,可能有效,也可能无效)

输出应显示无效设置操作产生的错误消息,然后显示玩家的最终属性:

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

例如,如果输入是 Hero、-20 和 5,输出应为:

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

生命值 setter 拒绝了 -20(生命值保持为 100),而等级 setter 接受了有效值 5。

如果输入是 Warrior、75 和 0,输出应为:

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

亲手试试

-- 加载 Player 模块
local Player = require('Player')

-- 读取输入
local name = io.read()
local healthValue = tonumber(io.read())
local levelValue = tonumber(io.read())

-- TODO: 用给定的名字创建一个新玩家

-- TODO: 尝试将玩家的生命值设置为 healthValue

-- TODO: 尝试将玩家的等级设置为 levelValue

-- TODO: 按以下格式输出玩家的最终属性:
-- 姓名:{name}
-- 生命值:{finalHealth}
-- 等级:{finalLevel}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Lua 在线编译器