extends : hériter d'une classe
Un CompteEpargne est un Compte avec un taux en plus. En PHP, on l'écrit avec extends : la classe fille récupère toutes les propriétés et méthodes public/protected du parent.
class Compte {
protected float $solde = 0; // protected → accessible aux filles
public function deposer(float $m): void { if ($m > 0) $this->solde += $m; }
public function getSolde(): float { return $this->solde; }
}
class CompteEpargne extends Compte {
public function __construct(private float $taux) {}
public function ajouterInterets(): void {
$this->deposer($this->solde * $this->taux); // réutilise la méthode héritée
}
}
Remarque : $solde est protected (pas private) pour rester accessible à la classe fille. private resterait invisible même pour les enfants.
public/protected du parent, puis ajoutent ou redéfinissent.parent:: et la redéfinition
Une fille peut redéfinir (override) une méthode du parent, et appeler la version parente avec parent::. Si la fille a son propre constructeur, elle doit appeler parent::__construct(...) pour initialiser la partie héritée.
class CompteCourant extends Compte {
public function __construct(private float $decouvertAutorise) {
parent::__construct(); // construit la partie "Compte"
}
// on REDÉFINIT retirer pour autoriser un découvert
public function retirer(float $m): bool {
if ($m > 0 && $m <= $this->solde + $this->decouvertAutorise) {
$this->solde -= $m;
return true;
}
return false;
}
}
Les classes abstraites : un gabarit
Une classe abstraite ne peut pas être instanciée directement : c'est un gabarit pour ses filles. Elle peut imposer des méthodes abstraites (sans corps) que chaque fille doit implémenter.
abstract class Forme {
abstract public function aire(): float; // pas de corps : à implémenter
public function decrire(): string { // méthode concrète partagée
return "Aire = " . $this->aire();
}
}
class Carre extends Forme {
public function __construct(private float $cote) {}
public function aire(): float { return $this->cote ** 2; }
}
// new Forme(); // ❌ Error: Cannot instantiate abstract class Forme
Exécute : héritage en action
<?php
class Compte {
protected float $solde = 0;
public function deposer(float $m): void { if ($m > 0) $this->solde += $m; }
public function getSolde(): float { return $this->solde; }
}
class CompteEpargne extends Compte {
public function __construct(private float $taux) {}
public function ajouterInterets(): void {
$this->deposer($this->solde * $this->taux);
}
}
$e = new CompteEpargne(0.05);
$e->deposer(1000); // méthode HÉRITÉE de Compte
$e->ajouterInterets(); // méthode PROPRE → +50
echo "Solde : " . $e->getSolde() . " €\n"; // 1050
?>
Tu veux un compte de support avec un plafond de retrait. L'IA te propose de faire hériter CompteSupport de CompteEpargne et passe $solde en public. Tu acceptes tel quel, ou tu rejettes ? Justifie.
class CompteSupport extends CompteEpargne { // CompteEpargne a déjà ajouterInterets()
public float $solde = 0; // public : on y accède de partout
public function retirer(float $m): void {
if ($m <= 1000) $this->solde -= $m; // plafond codé en dur
}
}
public float $solde casse l'encapsulation : n'importe quel code peut écrire $compte->solde = 999999 sans passer par deposer(). Le parent l'avait à juste titre en protected ; ici on l'expose pour rien. 2) Héritage abusif : un compte de support n'est pas un compte épargne, il hérite donc d'ajouterInterets() qui n'a aucun sens pour lui. La règle « est-un » n'est pas respectée. Le bon réflexe : garder $solde en protected et faire hériter CompteSupport de Compte (ou d'une classe/interface adaptée), pas d'CompteEpargne.Sans remonter dans la leçon : pourquoi met-on $solde en protected plutôt qu'en private dans Compte, et qu'est-ce qui empêche d'écrire new Forme() sur une classe abstraite ?
protected rend $solde accessible à la classe fille (ex. CompteEpargne qui lit $this->solde dans ajouterInterets()) ; private le rendrait invisible même pour les enfants. Pour la classe abstraite : abstract class Forme ne peut pas être instanciée parce qu'elle déclare au moins une méthode abstraite sans corps (aire()) ; PHP lève « Cannot instantiate abstract class Forme ». Elle sert de gabarit : seules ses filles, qui implémentent aire(), sont instanciables.L'abstraction « impose un contrat ». PHP a un outil dédié pour ça, plus souple que l'héritage : les interfaces.
Leçon 4 : interfaces →extends: inheriting from a class
A CompteEpargne is a Compte with an extra rate. In PHP, you write it with extends: the child class gets all the parent's public/protected properties and methods.
class Compte {
protected float $solde = 0; // protected → accessible to children
public function deposer(float $m): void { if ($m > 0) $this->solde += $m; }
public function getSolde(): float { return $this->solde; }
}
class CompteEpargne extends Compte {
public function __construct(private float $taux) {}
public function ajouterInterets(): void {
$this->deposer($this->solde * $this->taux); // reuses the inherited method
}
}
Note: $solde is protected (not private) so it stays accessible to the child class. private would be invisible even to children.
public/protected members, then add or override.parent:: and overriding
A child can override a parent method, and call the parent version with parent::. If the child has its own constructor, it must call parent::__construct(...) to initialize the inherited part.
class CompteCourant extends Compte {
public function __construct(private float $decouvertAutorise) {
parent::__construct(); // builds the "Compte" part
}
// we OVERRIDE retirer to allow an overdraft
public function retirer(float $m): bool {
if ($m > 0 && $m <= $this->solde + $this->decouvertAutorise) {
$this->solde -= $m;
return true;
}
return false;
}
}
Abstract classes: a template
An abstract class can't be instantiated directly: it's a template for its children. It can require abstract methods (no body) that each child must implement.
abstract class Forme {
abstract public function aire(): float; // no body: must be implemented
public function decrire(): string { // shared concrete method
return "Area = " . $this->aire();
}
}
class Carre extends Forme {
public function __construct(private float $cote) {}
public function aire(): float { return $this->cote ** 2; }
}
// new Forme(); // ❌ Error: Cannot instantiate abstract class Forme
Run it: inheritance in action
<?php
class Compte {
protected float $solde = 0;
public function deposer(float $m): void { if ($m > 0) $this->solde += $m; }
public function getSolde(): float { return $this->solde; }
}
class CompteEpargne extends Compte {
public function __construct(private float $taux) {}
public function ajouterInterets(): void {
$this->deposer($this->solde * $this->taux);
}
}
$e = new CompteEpargne(0.05);
$e->deposer(1000); // method INHERITED from Compte
$e->ajouterInterets(); // OWN method → +50
echo "Balance: " . $e->getSolde() . " €\n"; // 1050
?>
Abstraction "enforces a contract". PHP has a dedicated tool for that, more flexible than inheritance: interfaces.
Lesson 4: interfaces →