2) Organiser son code
Organiser son code avec des classes

Objectifs de la séance
- Comprendre le problème que les classes viennent résoudre.
- Créer une classe avec des propriétés et des méthodes.
- Contrôler l'accès aux données avec les mots-clés
privateetpublic. - Utiliser les accesseurs (
get/set) pour lire et modifier des propriétés de manière sécurisée. - Créer une classe fille qui hérite d'une classe parente avec
extends. - Déclarer une classe abstraite qui ne peut pas être instanciée directement.
Notions théoriques
Le problème des variables en vrac
À la fin de la séance 1, le code de index.php ressemblait à ceci :
$nom1 = "Lara";
$vie1 = 100;
$dps1 = 10;
$nom2 = "Mario";
$vie2 = 80;
$dps2 = 15;
Trois variables par personnage. Si l'on ajoute un troisième attribut demain (par exemple une armure),
il faut ajouter $armure1, $armure2, $armure3... Pour passer un personnage à une fonction,
on est obligé de transmettre toutes ses variables une par une :
simulerCombat($nom1, $vie1, $dps1, $nom2, $vie2, $dps2);
Six paramètres pour deux personnages. Avec une armure, ce serait huit. Ce code est difficile à lire et encore plus difficile à maintenir.
Les classes permettent de regrouper les données et les actions d'une entité dans un seul endroit.
Qu'est-ce qu'une classe ?
Une classe est un modèle. Elle décrit la structure d'un objet : quelles données il contient (ses propriétés) et quelles actions il peut effectuer (ses méthodes).
Un objet est une instance de la classe : c'est un exemplaire concret créé à partir du modèle.
L'analogie classique : une classe est comme un plan d'architecte, et un objet est la maison construite à partir de ce plan. On peut construire plusieurs maisons (objets) à partir du même plan (classe), chacune avec ses propres caractéristiques (couleur, surface...).
// Définir la classe (le modèle)
class Personnage {
// propriétés et méthodes...
}
// Créer des objets (des instances)
$p1 = new Personnage();
$p2 = new Personnage();
Propriétés et méthodes
Les propriétés sont les variables internes à la classe. Elles décrivent l'état de l'objet.
Les méthodes sont les fonctions internes à la classe. Elles décrivent le comportement de l'objet.
À l'intérieur d'une méthode, on accède aux propriétés et aux autres méthodes de la même classe
via $this (qui signifie "cet objet-ci", celui sur lequel on est en train de travailler) :
class Personnage {
public $nom;
public $vie;
public function sePresenter() {
print "<p>Je suis " . $this->nom . " et j'ai " . $this->vie . " points de vie.</p>";
}
}
$p = new Personnage();
$p->nom = "Lara";
$p->vie = 100;
$p->sePresenter(); // affiche : Je suis Lara et j'ai 100 points de vie.
Le constructeur
La méthode spéciale __construct est appelée automatiquement au moment où l'on crée un objet
avec new. Elle sert à initialiser les propriétés dès la création, plutôt que de les remplir
une par une ensuite.
class Personnage {
public $nom;
public $vie;
public function __construct($nom, $vie) {
$this->nom = $nom;
$this->vie = $vie;
}
}
$p = new Personnage("Lara", 100);
// $p->nom vaut "Lara", $p->vie vaut 100
Contrôler l'accès : private et public
Le mot-clé public signifie que la propriété ou la méthode est accessible depuis n'importe où
(depuis l'extérieur de la classe, depuis une autre classe...).
Le mot-clé private signifie que la propriété ou la méthode n'est accessible que depuis
l'intérieur de la classe elle-même.
Pourquoi utiliser private ? Pour se protéger des erreurs. Si $vie est publique, n'importe
quel code peut écrire $p->vie = -999; sans aucune vérification. Si elle est privée, on est
obligé de passer par une méthode setVie() qui peut vérifier que la valeur est cohérente
avant de l'enregistrer.
class Personnage {
private $vie;
public function setVie($vie) {
if (!is_numeric($vie)) {
print "La vie doit être un nombre";
return;
}
$this->vie = $vie;
}
public function getVie() {
return $this->vie;
}
}
Ces méthodes de lecture et de modification s'appellent des accesseurs :
getVie()est un "getter" (lire la propriété) ;setVie($vie)est un "setter" (modifier la propriété, avec validation).
La méthode __toString
PHP permet de définir ce qui doit être affiché quand on utilise print directement sur un objet.
C'est le rôle de la méthode spéciale __toString : elle doit renvoyer une chaîne de caractères.
public function __toString() {
return "Le personnage " . $this->nom . " a " . $this->vie . " points de vie";
}
$p = new Personnage("Lara", 100, 10);
print $p; // affiche : Le personnage Lara a 100 points de vie
L'héritage
L'héritage permet de créer une classe plus spécialisée à partir d'une classe existante. La classe fille récupère toutes les propriétés et méthodes de la classe parente, et peut en ajouter de nouvelles ou en redéfinir certaines.
On utilise le mot-clé extends :
class Guerrier extends Personnage {
public function __construct($nom, $vie, $dps, $mana) {
parent::__construct($nom, $vie, $dps, $mana); // transmet $mana au parent
}
public function attaquer($cible) {
// chaque sous-classe implémente sa propre logique d'attaque
}
}
parent::__construct(...) appelle le constructeur de la classe parente. C'est obligatoire
quand on redéfinit le constructeur dans une classe fille.
Une méthode de la classe fille peut aussi redéfinir (remplacer) une méthode du parent. C'est ce qu'on appelle la surcharge (override). La méthode de la classe fille prend le dessus sur celle du parent.
Les classes abstraites
Le mot-clé abstract devant une classe signifie qu'on ne peut pas créer d'objet directement
à partir d'elle. On doit obligatoirement passer par une classe fille.
C'est utile quand la classe parente est trop générique pour exister seule. Dans notre jeu,
il n'y a pas de "personnage générique" : il y a des guerriers, des mages, etc.
La classe Personnage n'existe que comme modèle commun ; c'est pourquoi elle est abstraite.
abstract class Personnage {
// ...
}
$p = new Personnage(...); // Erreur : impossible d'instancier une classe abstraite
$g = new Guerrier(...); // Correct : Guerrier est une classe fille concrète
Quelques rappels sur l'opérateur ternaire
-
Rappel sur la syntaxe de l'opérateur ternaire en PHP :
$result = condition ? valeur_si_vrai : valeur_si_faux;astucePour en savoir plus sur les opérateurs ternaires en PHP, consultez Opérateur ternaire.
-
Rappel sur la syntaxe de l'opérateur ternaire en Twig :
{{ condition ? 'valeur_si_vrai' : 'valeur_si_faux' }}