PHP Leçon 7
Les classes et les objets
Regrouper des données et les actions qui vont avec : déclarer une classe, créer des objets, écrire des méthodes et protéger les propriétés.
À la fin de cette leçon, tu sauras
- Déclarer une classe avec des propriétés et créer des objets avec new
- Écrire des méthodes et utiliser $this
- Initialiser un objet avec un constructeur
- Protéger une propriété avec private et passer par des méthodes
Pourquoi des objets ?
Imagine une application bancaire. Pour chaque compte, il faut le nom du titulaire et le solde, et des actions : déposer, retirer. Avec ce que tu connais, tu ferais un tableau associatif par compte et des fonctions à côté. Ça marche, mais rien n'empêche d'écrire $compte["solde"] = -1000000; par erreur, et les fonctions sont séparées des données qu'elles modifient.
La programmation orientée objet range ensemble les données et les actions. Deux mots à connaître :
- une classe est un plan : elle décrit ce qu'a et ce que sait faire un compte ;
- un objet est une chose construite à partir de ce plan : le compte de Léa, le compte de Tom. On peut en créer autant qu'on veut avec la même classe.
Déclarer une classe, créer un objet
Une classe se déclare avec le mot class suivi de son nom, qui commence par une majuscule (c'est l'usage). À l'intérieur, les propriétés sont les variables de l'objet.
<?php
class Compte
{
public string $titulaire = "";
public float $solde = 0;
}
$compteLea = new Compte(); // on construit un objet à partir du plan
$compteLea->titulaire = "Léa"; // -> pour accéder à une propriété
$compteLea->solde = 150;
$compteTom = new Compte(); // un deuxième objet, indépendant du premier
$compteTom->titulaire = "Tom";
echo $compteLea->titulaire . " a " . $compteLea->solde . " €"; // Léa a 150 €
echo $compteTom->solde; // 0new Compte()crée un nouvel objet ;- la flèche
->accède à une propriété de l'objet (attention : pas de$devant le nom de la propriété) ; publicveut dire que la propriété est utilisable partout. On verra plus bas pourquoi on préfère souventprivate.
Les méthodes et $this
Une méthode est une fonction écrite dans la classe : c'est une action que l'objet sait faire. Dans une méthode, $this désigne l'objet sur lequel on l'a appelée.
<?php
class Compte
{
public string $titulaire = "";
public float $solde = 0;
public function deposer(float $montant): void
{
$this->solde = $this->solde + $montant;
}
public function decrire(): string
{
return "$this->titulaire a $this->solde €";
}
}
$compteLea = new Compte();
$compteLea->titulaire = "Léa";
$compteLea->deposer(100);
$compteLea->deposer(50);
echo $compteLea->decrire(); // Léa a 150 €Quand on écrit $compteLea->deposer(100), PHP exécute la méthode deposer avec $this = $compteLea. Si on l'appelait sur $compteTom, $this serait $compteTom. Le mot void indique que la méthode ne renvoie rien.
Le constructeur
Créer un objet puis remplir ses propriétés une par une, c'est long, et on peut oublier une étape. Le constructeur est une méthode spéciale, __construct (avec deux tirets bas), appelée automatiquement par new. Les valeurs données entre les parenthèses de new lui sont transmises.
<?php
class Compte
{
public string $titulaire;
public float $solde;
public function __construct(string $titulaire, float $solde = 0)
{
$this->titulaire = $titulaire;
$this->solde = $solde;
}
}
$compteLea = new Compte("Léa", 150); // le constructeur reçoit "Léa" et 150
$compteTom = new Compte("Tom"); // solde = 0 par défautDepuis PHP 8, il existe un raccourci : en mettant public (ou private) devant un paramètre du constructeur, PHP crée la propriété et la remplit tout seul. Les deux versions font exactement la même chose :
<?php
class Compte
{
public function __construct(public string $titulaire, public float $solde = 0)
{
}
}Protéger les propriétés : private
Avec public, n'importe quel code peut écrire $compte->solde = -1000000;. Avec private, la propriété n'est utilisable qu'à l'intérieur de la classe. Le reste du programme doit passer par des méthodes publiques, qui peuvent vérifier les valeurs. C'est l'encapsulation.
<?php
class Compte
{
private float $solde = 0;
public function __construct(public string $titulaire)
{
}
public function deposer(float $montant): void
{
if ($montant <= 0) {
echo "Montant refusé";
return;
}
$this->solde += $montant;
}
public function getSolde(): float
{
return $this->solde;
}
}
$compte = new Compte("Léa");
$compte->deposer(80);
echo $compte->getSolde(); // 80
echo $compte->solde; // Erreur : Cannot access private property Compte::$soldeUne méthode qui sert seulement à lire une propriété privée s'appelle un accesseur (en anglais « getter ») : par convention, son nom commence par get. Ici, le solde ne peut changer que par deposer(), qui refuse les montants négatifs.
Astuce : $this->solde += $montant; est un raccourci pour $this->solde = $this->solde + $montant;. Il existe aussi -=, *=…
Attention : pas de $ après la flèche. On écrit $this->solde, jamais $this->$solde.
À retenir
- Une classe est un plan ; un objet est construit à partir de ce plan avec
new. - Les propriétés sont les variables de l'objet, les méthodes ses actions. On y accède avec la flèche :
$objet->propriete,$objet->methode(). - Dans une méthode,
$thisdésigne l'objet sur lequel on l'a appelée. - Le constructeur
__construct()est appelé parnew; le raccourcipublic string $nomdans ses paramètres crée et remplit la propriété. private: utilisable seulement dans la classe ; on passe alors par des méthodes publiques (accesseursgetSolde()), qui peuvent vérifier les valeurs.
Voir la fiche de révision de cette leçon (à imprimer ou à relire avant un contrôle)
Exercice 1 · Ta première classe
Facile ✓ RéussiLa classe Livre est déjà déclarée avec deux propriétés publiques. Sous la classe :
- crée un objet
$livreavecnew Livre(); - donne-lui un titre et un auteur avec la flèche
->; - affiche « Le Petit Prince, de Saint-Exupéry » (ou ton livre préféré) en lisant les deux propriétés.
Clique sur ▶ Exécuter (ou Ctrl + Entrée) pour lancer ton code.
Données envoyées par le formulaire
Consignes à réussir
- À faire : Un objet est créé avec new Livre()
- À faire : Le titre est rempli avec ->titre
- À faire : L'auteur est rempli avec ->auteur
- À faire : L'affichage lit les deux propriétés
- À faire : La page affiche « …, de … » ▶ vérifié quand tu exécutes
Bravo, cet exercice est réussi !
- Indice 1 : Créer l'objet :
$livre = new Livre();. - Indice 2 : Remplir une propriété :
$livre->titre = "Le Petit Prince";(pas de$devanttitre). - Indice 3 : Afficher avec la concaténation :
echo $livre->titre . ", de " . $livre->auteur;.
Toujours bloqué ? Voir une solution
<?php
class Livre
{
public string $titre = "";
public string $auteur = "";
}
$livre = new Livre();
$livre->titre = "Le Petit Prince";
$livre->auteur = "Saint-Exupéry";
echo $livre->titre . ", de " . $livre->auteur; Exercice 2 · Méthodes et constructeur
Moyen ✓ RéussiComplète la classe Personnage d'un jeu :
- un constructeur qui reçoit un
$nomet remplit la propriéténom; - une méthode
soigner(int $points)qui ajoute les points àvie, sans dépasser 100 ; - une méthode
decrire()qui renvoie « Zelda : 100 PV » (nom, deux-points, vie, « PV »).
Le code sous la classe crée Zelda avec 60 PV, la soigne de 50 et affiche sa description : le résultat attendu est « Zelda : 100 PV ».
Clique sur ▶ Exécuter (ou Ctrl + Entrée) pour lancer ton code.
Données envoyées par le formulaire
Consignes à réussir
- À faire : Un constructeur __construct reçoit $nom
- À faire : soigner() modifie $this->vie
- À faire : decrire() renvoie le texte avec return
- À faire : La vie ne dépasse pas 100
- À faire : La page affiche « Zelda : 100 PV » ▶ vérifié quand tu exécutes
Bravo, cet exercice est réussi !
- Indice 1 : Le constructeur :
public function __construct(string $nom) { $this->nom = $nom; }, avec deux tirets bas. - Indice 2 : Pour soigner sans dépasser 100 : ajoute d'abord (
$this->vie += $points;), puisif ($this->vie > 100) { $this->vie = 100; }. - Indice 3 :
decrire()renvoie un texte :return "$this->nom : $this->vie PV";. C'est leechodu bas qui l'affiche.
Toujours bloqué ? Voir une solution
<?php
class Personnage
{
public string $nom;
public int $vie = 60;
public function __construct(string $nom)
{
$this->nom = $nom;
}
public function soigner(int $points): void
{
$this->vie += $points;
if ($this->vie > 100) {
$this->vie = 100;
}
}
public function decrire(): string
{
return "$this->nom : $this->vie PV";
}
}
$zelda = new Personnage("Zelda");
$zelda->soigner(50);
echo $zelda->decrire(); Exercice 3 · Un compte bien protégé
Pour aller plus loin ✓ RéussiÉcris une classe Compte dont le solde est privé :
- une propriété
private float $solde = 0;; - un constructeur avec le raccourci de PHP 8 :
public string $titulaireen paramètre ; - une méthode
deposer(float $montant)qui refuse les montants négatifs ou nuls (elle ne change alors rien) ; - une méthode
retirer(float $montant)qui refuse si le solde est insuffisant, et renvoietruesi le retrait a eu lieu,falsesinon ; - un accesseur
getSolde().
Le programme du bas teste ta classe : il doit afficher « Retrait refusé » puis « Léa : 70 € ».
Clique sur ▶ Exécuter (ou Ctrl + Entrée) pour lancer ton code.
Données envoyées par le formulaire
Consignes à réussir
- À faire : Le solde est une propriété private
- À faire : Le constructeur utilise le raccourci public string $titulaire
- À faire : deposer() vérifie le montant
- À faire : retirer() renvoie true ou false
- À faire : Un accesseur getSolde() renvoie le solde
- À faire : La page affiche « Retrait refusé » puis « Léa : 70 € » ▶ vérifié quand tu exécutes
Bravo, cet exercice est réussi !
- Indice 1 : La structure :
class Compte { private float $solde = 0; public function __construct(public string $titulaire) { } … }. Le corps du constructeur reste vide : PHP remplittitulairetout seul. - Indice 2 :
deposer:if ($montant <= 0) { return; }puis$this->solde += $montant;. Unreturn;sans valeur arrête la méthode. - Indice 3 :
retirer:if ($montant > $this->solde) { return false; }, sinon on enlève le montant etreturn true;. EtgetSolde()faitreturn $this->solde;.
Toujours bloqué ? Voir une solution
<?php
class Compte
{
private float $solde = 0;
public function __construct(public string $titulaire)
{
}
public function deposer(float $montant): void
{
if ($montant <= 0) {
return;
}
$this->solde += $montant;
}
public function retirer(float $montant): bool
{
if ($montant > $this->solde) {
return false;
}
$this->solde -= $montant;
return true;
}
public function getSolde(): float
{
return $this->solde;
}
}
$compte = new Compte("Léa");
$compte->deposer(100);
$compte->deposer(-20);
$compte->retirer(30);
if (!$compte->retirer(500)) {
echo "<p>Retrait refusé</p>";
}
echo "<p>" . $compte->titulaire . " : " . $compte->getSolde() . " €</p>";