Logique de validation
Fait partie de la section Object Oriented Programming du Journey Lua de Coddy — leçon 47 sur 70.
Jusqu'à présent, nous avons exploré différentes manières de protéger les données : les conventions de nommage signalent l'intention, les fermetures (closures) masquent complètement les variables, et les tables en lecture seule empêchent toute modification. Mais souvent, vous avez besoin d'un juste milieu : permettre des modifications, mais seulement celles qui sont valides.
C'est là que les méthodes de type « setter » deviennent puissantes. Au lieu de simplement assigner une valeur, un setter peut vérifier si la nouvelle valeur est cohérente avant de l'accepter :
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
endLorsque quelqu'un appelle person:setAge(-5), la méthode intercepte l'entrée non valide et refuse la mise à jour. L'état de l'objet reste cohérent. Sans cette protection, des données erronées pourraient corrompre silencieusement votre programme — imaginez le calcul des prestations de retraite avec un âge négatif.
La validation peut être aussi simple ou complexe que nécessaire. Vous pourriez vérifier des plages de valeurs, vérifier des types ou vous assurer que les valeurs correspondent aux formats attendus. Le principe clé est que le setter agit comme un garde-barrière, garantissant que seules des données cohérentes entrent dans votre objet.
Défi
FacileConstruisons une classe Player qui protège ses attributs de santé et de niveau en utilisant une logique de validation dans les méthodes setter ! Cela garantit que les personnages du jeu ne se retrouvent jamais avec des statistiques impossibles.
Vous organiserez votre code sur deux fichiers :
Player.lua: Créez une classe qui gère les statistiques d'un joueur avec une validation appropriée. Le constructeur:new(name)doit initialiser le joueur avec un nom,_healthdéfini sur100, et_leveldéfini sur1. Incluez ces méthodes ::getName()— retourne le nom du joueur:getHealth()— retourne la santé actuelle:getLevel()— retourne le niveau actuel:setHealth(value)— met à jour la santé uniquement si la valeur est comprise entre 0 et 100 (inclus). Si elle est invalide, affichezError: Health must be between 0 and 100et ne modifiez pas la valeur.:setLevel(value)— met à jour le niveau uniquement si la valeur est égale ou supérieure à 1. Si elle est invalide, affichezError: Level must be at least 1et ne modifiez pas la valeur.
main.lua: Importez votre module Player et lisez un nom de joueur, puis deux valeurs pour tester les setters. Créez un joueur, tentez de définir sa santé sur la première valeur, tentez de définir son niveau sur la seconde valeur, puis affichez les statistiques finales du joueur.
Vous recevrez trois entrées :
- Le nom du joueur
- Une valeur de santé à tenter de définir (un nombre, qui pourrait être valide ou invalide)
- Une valeur de niveau à tenter de définir (un nombre, qui pourrait être valide ou invalide)
Votre sortie doit afficher tous les messages d'erreur provenant de tentatives invalides, suivis des statistiques finales du joueur :
Name: {name}
Health: {finalHealth}
Level: {finalLevel}Par exemple, si les entrées sont Hero, -20, et 5, la sortie devrait être :
Error: Health must be between 0 and 100
Name: Hero
Health: 100
Level: 5Le setter de santé a rejeté -20 (maintenant la santé à 100), tandis que le setter de niveau a accepté 5 comme valide.
Si les entrées sont Warrior, 75, et 0, la sortie devrait être :
Error: Level must be at least 1
Name: Warrior
Health: 75
Level: 1Aide-mémoire
Les méthodes setter vous permettent de valider les données avant de mettre à jour les propriétés de l'objet, garantissant que seules les valeurs valides sont acceptées.
Un setter de base avec validation :
function Person:setAge(newAge)
if newAge < 0 then
print("Error: Age cannot be negative")
return
end
self._age = newAge
endLe setter agit comme un garde-barrière — il vérifie si la nouvelle valeur est valide avant de mettre à jour la propriété interne. Si la validation échoue, il affiche une erreur et s'arrête prématurément sans modifier les données.
La validation peut inclure :
- Des vérifications de plage (par ex., age >= 0)
- Des limites de bornes (par ex., 0 <= health <= 100)
- La vérification de type
- La validation de format
Cela empêche les données invalides de corrompre l'état de votre objet et maintient la cohérence de votre programme.
Essayez vous-même
-- Charger le module Player
local Player = require('Player')
-- Lire les entrées
local name = io.read()
local healthValue = tonumber(io.read())
local levelValue = tonumber(io.read())
-- TODO : Créer un nouveau joueur avec le nom donné
-- TODO : Tenter de définir la santé du joueur à healthValue
-- TODO : Tenter de définir le niveau du joueur à levelValue
-- TODO : Afficher les statistiques finales du joueur au format :
-- Nom : {name}
-- Santé : {finalHealth}
-- Niveau : {finalLevel}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Object Oriented Programming
1Le concept de « self »
Tables avec fonctions« self » expliciteLa syntaxe avec deux-pointsPoint vs deux-pointsRécapitulatif - Point mobile4Projet : Banque numérique
Configuration du projetMéthode de dépôt7Polymorphisme et Redéfinition
Redéfinition de méthodesAppeler des méthodes parentesDuck TypingInterface communeVérification du typeRécapitulatif - Rôles des employés10Projet : Gestionnaire de formes
Configuration du projetClasse Rectangle2Modèle de prototype de classe
Le concept de prototypeLiaison avec __indexLe constructeur :new()Initialisation des attributsInstances indépendantesRécapitulatif - Usine de voitures5Surcharge d'opérateurs en POO
Additionner des objetsSoustraire des objetsConcaténer des objetsComparer des objets (<, >)Récapitulatif - Calculs de portefeuille8Encapsulation
Conventions de nommageClosures pour la confidentialitéAccès via les ClosuresTables en lecture seuleLogique de validationRécapitulatif - Coffre-fort sécurisé11Patrons de conception (Lite)
Fonctions FactoryTable SingletonPatron IteratorObserver (Écouteur)Récapitulatif - Logger Factory3État et comportement des objets
Variables d'instanceMéthodes GetterMéthodes SetterPropriétés calculéesFormatage de chaînesVérifications d'égalitéRécapitulatif - Note de l'étudiant6Bases de l'héritage
Mise en place de l'héritageHériter des méthodesÉtendre le constructeurAjouter des méthodes enfantsPartagé vs UniqueRécapitulatif - Hiérarchie des formes