Logique de validation
Fait partie de la section Programmation orientée objet du Journey Lua de Coddy. Leçon 47 sur 70.
Jusqu’à présent, nous avons exploré différentes façons de protéger les données : les conventions de nommage indiquent l’intention, les clôtures masquent complètement les variables, et les tables en lecture seule empêchent toute modification. Mais souvent, vous avez besoin de quelque chose entre les deux : autoriser les modifications, mais uniquement celles qui sont valides.
C’est ici que les méthodes setter deviennent puissantes. Au lieu de simplement affecter 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
endLorsqu'une personne appelle person:setAge(-5), la méthode intercepte l'entrée non valide et refuse de mettre à jour la valeur. L'état de l'objet reste cohérent. Sans cette protection, de mauvaises données pourraient corrompre silencieusement votre programme : imaginez calculer des prestations de retraite avec un âge négatif.
La validation peut être aussi simple ou complexe que nécessaire. Vous pouvez vérifier des plages de valeurs, contrôler les types ou vous assurer que les valeurs correspondent aux formats attendus. Le principe essentiel est que le setter joue le rôle de gardien, en veillant à ce que seules des données cohérentes soient introduites dans votre objet.
Défi
FacileConstruisons une classe Player qui protège ses attributs de santé et de niveau grâce à une logique de validation dans les méthodes setter ! Cela garantit que les personnages du jeu ne puissent jamais se retrouver avec des statistiques impossibles.
Tu organiseras ton code sur deux fichiers :
Player.lua: crée 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 à100et_leveldéfini à1. Inclus ces méthodes ::getName(): renvoie le nom du joueur:getHealth(): renvoie la santé actuelle:getLevel(): renvoie le niveau actuel:setHealth(value): met à jour la santé uniquement si la valeur est comprise entre 0 et 100 (inclus). Si elle est invalide, afficheError: Health must be between 0 and 100et ne modifie pas la valeur.:setLevel(value): met à jour le niveau uniquement si la valeur est supérieure ou égale à 1. Si elle est invalide, afficheError: Level must be at least 1et ne modifie pas la valeur.
main.lua: importe ton module Player et lis un nom de joueur, puis deux valeurs pour tester les setters. Crée un joueur, essaie de définir sa santé à la première valeur, essaie de définir son niveau à la deuxième valeur, puis affiche les statistiques finales du joueur.
Tu recevras trois entrées :
- Le nom du joueur
- Une valeur de santé à tenter de définir (un nombre, qui peut être valide ou invalide)
- Une valeur de niveau à tenter de définir (un nombre, qui peut être valide ou invalide)
Ta sortie doit afficher les éventuels messages d'erreur correspondant aux 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 doit être :
Error: Health must be between 0 and 100
Name: Hero
Health: 100
Level: 5Le setter de santé a rejeté -20 (en conservant la santé à 100), tandis que le setter de niveau a accepté 5 comme valeur valide.
Si les entrées sont Warrior, 75 et 0, la sortie doit être :
Error: Level must be at least 1
Name: Warrior
Health: 75
Level: 1Essayez vous-même
-- Requiert 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 Programmation orientée objet
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 RectangleClasse CercleMéthode PérimètreCollection de formesAire totaleFiltrer les formes2Modè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 formesEntraînez-vous par vous-même : Compilateur Lua en ligne