Menu
Coddy logo textTech

Логика валидации

Часть раздела Объектно-ориентированное программирование путешествия по Lua на Coddy. Урок 47 из 70.

До сих пор мы рассматривали разные способы защиты данных: соглашения об именовании указывают на назначение, замыкания полностью скрывают переменные, а таблицы, доступные только для чтения, предотвращают любые изменения. Но часто нужно нечто среднее: разрешить изменения, но только допустимые.

Именно здесь методы-сеттеры становятся мощным инструментом. Вместо того чтобы просто присваивать значение, сеттер может проверить, имеет ли новое значение смысл, прежде чем принять его:

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, который защищает свои атрибуты здоровья и уровня с помощью логики проверки в методах-сеттерах! Это гарантирует, что игровые персонажи никогда не получат невозможные характеристики.

Вы организуете код в двух файлах:

  • Player.lua: создайте класс, который управляет характеристиками игрока с корректной проверкой. Конструктор :new(name) должен инициализировать игрока с именем, значением 100 для _health и значением 1 для _level. Включите следующие методы:
    • :getName(): возвращает имя игрока
    • :getHealth(): возвращает текущее здоровье
    • :getLevel(): возвращает текущий уровень
    • :setHealth(value): обновляет здоровье, только если значение находится между 0 и 100 (включительно). Если значение недействительно, выведите Error: Health must be between 0 and 100 и не изменяйте значение.
    • :setLevel(value): обновляет уровень, только если значение равно 1 или больше. Если значение недействительно, выведите Error: Level must be at least 1 и не изменяйте значение.
  • main.lua: подключите свой модуль Player и считайте имя игрока, затем два значения для проверки сеттеров. Создайте игрока, попытайтесь установить его здоровье в первое значение, попытайтесь установить его уровень во второе значение, затем выведите итоговые характеристики игрока.

Вы получите три входных значения:

  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

Сеттер здоровья отклонил значение -20 (сохранив здоровье равным 100), а сеттер уровня принял значение 5 как допустимое.

Если входными значениями являются Warrior, 75 и 0, вывод должен быть таким:

Error: Level must be at least 1
Name: Warrior
Health: 75
Level: 1
ТРЕБУЕМЫЙ ФОРМАТ ВЫВОДА: <translation> [Ваш переведённый контент здесь] </translation>

Попробуйте сами

-- Подключить модуль 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