Getters et setters
La programmation orientée objet en PHP : méthode pour contrôler les modifications d'une variable
Personnages toujours égaux
Un petit problème se pose. Puisque, à la base, les deux personnages ont le même niveau de dégâts, la même expérience et la même force, ils seront à la fin toujours égaux. Pour pallier ce problème, il faudrait pouvoir assigner des valeurs spécifiques aux deux personnages, afin que le combat puisse les différencier. Or, vous ne pouvez pas accéder aux attributs en-dehors de la classe ! Par conséquent, si vous voulez récupérer un attribut, il va falloir le demander à la classe, de même si vous voulez les modifier.Afficher, à la fin du script, la force, l'expérience et le niveau de dégâts de chaque personnage :
<?php
// ...
$perso1 = new Personnage; // Un premier personnage
$perso2 = new Personnage; // Un second personnage
$perso1->frapper($perso2); // $perso1 frappe $perso2
$perso1->gagnerExperience(); // $perso1 gagne de l'expérience
$perso2->frapper($perso1); // $perso2 frappe $perso1
$perso2->gagnerExperience(); // $perso2 gagne de l'expérience
echo 'Le personnage 1 a ', $perso1->force(), ' de force, comme le personnage 2 qui a ', $perso2->force(), ' de force.<br>';
echo 'Le personnage 1 a ', $perso1->experience(), ' d\'expérience, comme le personnage 2 qui a ', $perso2->experience(), ' d\'expérience.<br>';
echo 'Le personnage 1 a ', $perso1->degats(), ' de dégâts, comme le personnage 2 qui a ', $perso2->degats(), ' de dégâts.<br>';
Accéder à un attribut : l'accesseur (ou getters)
À votre avis, comment peut-on faire pour récupérer la valeur d'un attribut ? La solution est simple : nous allons implémenter des méthodes dont le seul rôle sera de nous donner l'attribut qu'on leur demande ! Ces méthodes ont un nom bien spécial : ce sont des accesseurs (ou getters).Voici la liste des accesseurs de notre classe Personnage:
<?php
class Personnage {
private $_force;
private $_experience;
private $_degats;
public function frapper(Personnage $persoAFrapper) {
$persoAFrapper->_degats += $this->_force;
}
public function gagnerExperience() {
// Ceci est un raccourci qui équivaut à écrire "$this->_experience = $this->_experience + 1"
// On aurait aussi pu écrire "$this->_experience += 1"
$this->_experience++;
}
// Ceci est la méthode degats() : elle se charge de renvoyer le contenu de l'attribut $_degats.
public function degats() {
return $this->_degats;
}
// Ceci est la méthode force() : elle se charge de renvoyer le contenu de l'attribut $_force.
public function force() {
return $this->_force;
}
// Ceci est la méthode experience() : elle se charge de renvoyer le contenu de l'attribut $_experience.
public function experience() {
return $this->_experience;
}
}
Modifier la valeur d'un attribut : les mutateur (ou setters)
La classe doit impérativement contrôler la valeur afin d'assurer son intégrité car, si elle ne le fait pas, on pourra passer n'importe quelle valeur à la classe et le principe d'encapsulation n'est plus respecté ! Ces méthodes ont aussi un nom spécial : il s'agit de mutateurs (ou setters). Ces méthodes sont de la forme setNomDeLAttribut().Voici la liste des mutateurs (ajoutée à la liste des accesseurs) de notre classe Personnage:
<?php
class Personnage {
private $_force;
private $_experience;
private $_degats;
public function frapper(Personnage $persoAFrapper) {
$persoAFrapper->_degats += $this->_force;
}
public function gagnerExperience() {
$this->_experience++;
}
// Mutateur chargé de modifier l'attribut $_force.
public function setForce($force) {
if (!is_int($force)) {
// S'il ne s'agit pas d'un nombre entier.
trigger_error('La force d\'un personnage doit être un nombre entier', E_USER_WARNING);
return;
}
if ($force > 100) {
// On vérifie bien qu'on ne souhaite pas assigner une valeur supérieure à 100.
trigger_error('La force d\'un personnage ne peut dépasser 100', E_USER_WARNING); // déclenche une erreur utilisateur
return;
}
$this->_force = $force;
}
// Mutateur chargé de modifier l'attribut $_experience.
public function setExperience($experience) {
if (!is_int($experience)) {
// S'il ne s'agit pas d'un nombre entier.
trigger_error('L\'expérience d\'un personnage doit être un nombre entier', E_USER_WARNING);
return;
}
if ($experience > 100) {
// On vérifie bien qu'on ne souhaite pas assigner une valeur supérieure à 100.
trigger_error('L\'expérience d\'un personnage ne peut dépasser 100', E_USER_WARNING);
return;
}
$this->_experience = $experience;
}
// Ceci est la méthode degats() : elle se charge de renvoyer le contenu de l'attribut $_degats.
public function degats() {
return $this->_degats;
}
// Ceci est la méthode force() : elle se charge de renvoyer le contenu de l'attribut $_force.
public function force() {
return $this->_force;
}
// Ceci est la méthode experience() : elle se charge de renvoyer le contenu de l'attribut $_experience.
public function experience() {
return $this->_experience;
}
}
Modifier la valeur de la force et de l'expérience des deux personnages
Maintenant, on peut assigner des valeurs spécifiques de force et d'expérience aux deux personnages.<?php
$perso1 = new Personnage; // Un premier personnage
$perso2 = new Personnage; // Un second personnage
$perso1->setForce(10);
$perso1->setExperience(2);
$perso2->setForce(90);
$perso2->setExperience(58);
$perso1->frapper($perso2); // $perso1 frappe $perso2
$perso1->gagnerExperience(); // $perso1 gagne de l'expérience
$perso2->frapper($perso1); // $perso2 frappe $perso1
$perso2->gagnerExperience(); // $perso2 gagne de l'expérience
echo 'Le personnage 1 a ', $perso1->force(), ' de force, contrairement au personnage 2 qui a ', $perso2->force(), ' de force.<br>';
echo 'Le personnage 1 a ', $perso1->experience(), ' d\'expérience, contrairement au personnage 2 qui a ', $perso2->experience(), ' d\'expérience.<br>';
echo 'Le personnage 1 a ', $perso1->degats(), ' de dégâts, contrairement au personnage 2 qui a ', $perso2->degats(), ' de dégâts.<br>';