3.2Programmation orientée objet (classes, héritage, interfaces)
L'essentiel en 30 secondes
- La classe est un modèle, l'objet une instance : propriétés (données) + méthodes (comportements), new pour créer, $this pour l'objet courant, __construct pour initialiser.
- L'encapsulation protège l'état : propriétés private + getters/setters qui valident — l'objet garantit sa propre cohérence.
- Héritage, interfaces et traits structurent : extends pour spécialiser, interface pour contracter, trait pour partager sans héritage.
Mini-cas filé — Riad range son code spaghetti en objets
Riad, développeur web à Constantine, gère utilisateurs et commandes avec des tableaux et des fonctions dispersées : un email invalide glissé n'importe où casse l'envoi. Il modélise une classe Utilisateur (propriétés private, setters qui valident, constructeur qui initialise), une classe Admin qui extends Utilisateur, et une interface Notifiable que les deux implémentent. Les données invalides sont rejetées à la source, le code se lit comme le métier.
Ce même cas revient dans le cours, le schéma, le script et le défi 48h.
1. Classes, objets et encapsulation
La POO organise le code autour d'objets regroupant données et comportements. La classe est le modèle : propriétés (un utilisateur a un nom, un email) et méthodes (il peut se connecter). On crée des objets avec $user = new User(), le constructeur __construct() initialise à la création, et $this désigne l'objet courant ($this->nom).
L'encapsulation contrôle l'accès via la visibilité : public (partout), private (classe seule), protected (classe + descendantes). On rend les propriétés private et on y accède par des getters/setters qui valident : impossible de poser un email invalide directement. L'objet protège son état — principe clé de robustesse que Riad applique à chaque entité.
2. Héritage, polymorphisme, interfaces et traits
L'héritage (class Admin extends User) fait réutiliser et spécialiser : Admin obtient tout de User, ajoute ou redéfinit des méthodes. Le polymorphisme permet à des classes différentes de répondre à la même méthode chacune à sa façon — idéal pour du code générique. L'abstraction masque la complexité derrière des interfaces simples.
Les interfaces sont des contrats : elles déclarent des méthodes qu'une classe DOIT implémenter, sans dire comment — on programme « par contrat », on découple (indispensable pour tester). Les traits partagent des méthodes entre classes sans héritage (PHP n'autorise qu'un seul extends). Riad en retient la hiérarchie : contrat d'abord (interface), partage ensuite (trait), spécialisation enfin (extends).
Le $this qui se prend pour les autres
Private d'abord : un objet garde ses affaires pour lui.
🔎 Exemple concret — Classe encapsulée et héritage
Riad modélise un utilisateur qui valide son email, puis un admin.
nom = $nom;
$this->setEmail($email);
}
public function setEmail(string $email): void {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException('Email invalide.');
}
$this->email = $email;
}
public function getEmail(): string { return $this->email; }
}
class Admin extends Utilisateur {
public function peutAcceder(string $ressource): bool { return true; }
}
Lecture : constructeur qui initialise, setter private-backed qui valide, héritage qui spécialise.
Leçon : un email invalide est rejeté à la source — l'objet garantit sa cohérence.
Vocabulaire de la section
- POO / classe / objet
- Paradigme organisant le code en objets (données + comportements) ; la classe est le modèle, l'objet une instance (new) ; $this = courant, __construct = initialisation.
Exemple simple : new Utilisateur('Riad', 'riad@exemple-fictif.test').
Ce que ce n'est pas : des fonctions et variables dispersées sans modèle.
Réflexe : modéliser chaque entité métier en classe.
- Encapsulation / visibilité
- Regrouper et contrôler l'accès : public (partout), private (classe seule), protected (classe + descendantes) ; private + getters/setters pour protéger l'état.
Exemple simple : Le setEmail de Riad qui refuse l'invalide.
Ce que ce n'est pas : des propriétés public modifiables n'importe comment.
Réflexe : propriétés private par défaut.
- Héritage
- class Admin extends User : réutilise les membres du parent, ajoute ou redéfinit ; relation « est un type de ».
Exemple simple : Admin hérite d'Utilisateur et redéfinit peutAcceder().
Ce que ce n'est pas : du copier-coller de méthodes entre classes.
Réflexe : hériter pour spécialiser, pas pour copier.
- Polymorphisme / abstraction
- Même méthode, comportements différents selon la classe ; masquer la complexité derrière des interfaces simples.
Exemple simple : Chaque rôle répond à peutAcceder() à sa façon.
Ce que ce n'est pas : un switch géant sur le type d'objet.
Réflexe : appeler la méthode, laisser l'objet décider.
- Interfaces / traits
- Interface : contrat de méthodes à implémenter (découpler, tester). Trait : partage horizontal de méthodes sans héritage.
Exemple simple : Notifiable implémentée par Utilisateur et Commande.
Ce que ce n'est pas : dépendre partout d'une classe concrète.
Réflexe : dépendre d'interfaces, partager par traits.
En pratique — Penser et programmer en objets
- Créez une classe (ex. User) avec des propriétés (nom, email) et des méthodes ; instanciez avec `new`, initialisez via __construct, utilisez $this.
- Appliquez l'ENCAPSULATION : propriétés private, accès via getters/setters qui valident ; typez les propriétés.
- Créez une classe qui HÉRITE (extends) et REDÉFINIT une méthode ; observez réutilisation et spécialisation.
- Définissez une INTERFACE (contrat) et une classe qui l'implémente ; explorez un trait pour partager des méthodes.
Script prêt à dire — présenter sa modélisation objet (30 s)
« Les utilisateurs sont modélisés en classe : propriétés private, constructeur qui initialise, setters qui valident l'email. Admin hérite d'Utilisateur et redéfinit ses droits, et les deux implémentent l'interface Notifiable. Une donnée invalide est rejetée à la source. »
À dire en revue ; montrer le setter qui lève l'exception.
Modèle copier-coller — classe encapsulée + interface
nom = $nom;
$this->setEmail($email);
}
public function setEmail(string $email): void {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException('Email invalide.');
}
$this->email = $email;
}
public function getEmail(): string { return $this->email; }
}
class Admin extends Utilisateur {
public function peutAcceder(string $ressource): bool { return true; }
}
Indépendant
Une classe Client encapsulée suffit à fiabiliser les devis générés.
PME à Constantine
Riad modélise clients, commandes et admins liés, chacun validant son état.
Équipe produit
Imposer interfaces et encapsulation pour des modules testables entre équipes.
Débutant
Cette semaine : une classe à deux propriétés private et un setter qui valide.
✓ Bonnes pratiques
- Propriétés private par défaut, accès via des méthodes qui valident.
- Typer propriétés et signatures (robustesse + lisibilité).
- Programmer par contrat (interfaces) pour découpler et tester.
✗ Pièges fréquents
- Tout mettre en public (état corruptible de partout).
- Hériter pour copier du code au lieu de spécialiser un « est un ».
- Confondre interface (contrat) et héritage (réutilisation).
Points clés à retenir
- La POO organise le code en OBJETS (données + comportements). CLASSE = modèle ; OBJET = instance (new). $this = courant ; __construct = initialisation.
- ENCAPSULATION : VISIBILITÉ (public/private/protected) ; private + getters/setters qui valident pour protéger l'état. HÉRITAGE (extends) : réutiliser et spécialiser.
- POLYMORPHISME (même méthode, implémentations différentes) et ABSTRACTION. INTERFACES = contrats (découpler, tester) ; TRAITS = partage sans héritage.
- La POO est le CAP du PHP moderne et des FRAMEWORKS : organiser, réutiliser, maintenir — un changement de pensée qui demande de la pratique.
Défi 48h — appliquez demain
Écrivez 1 classe encapsulée (private + setter qui valide) et 1 classe fille qui redéfinit 1 méthode.
- Je distingue classe (modèle) et objet (instance).
- Mes propriétés sont private avec validation.
- J'hérite pour spécialiser et je contracte par interface.
Questions fréquentes
Pourquoi passer à la POO alors que le procédural fonctionne ?
Le procédural disperse données et fonctions sans structure : sur une appli qui grandit, on ne sait plus quelles fonctions vont avec quelles données. La POO regroupe (objet = données + comportements), modélise le métier (Utilisateur, Commande), protège l'état (encapsulation) et réutilise (héritage, traits) tout en découplant (interfaces). C'est le paradigme des frameworks du niveau 4 — le cap à franchir.
Encapsulation, héritage, interfaces : comment les comprendre concrètement ?
Encapsulation = protéger et regrouper : le solde d'un compte ne change que via deposer/retirer qui vérifient (jamais d'affectation directe). Héritage = « est un type de » : Chien extends Animal réutilise et spécialise (aboyer). Interface = contrat : la classe s'engage à fournir des méthodes, le reste du code dépend du contrat (testable). Trait = partage horizontal quand un seul extends ne suffit pas.
Pourquoi des propriétés private + getters/setters ?