Programmation Orientée Objet
Cours Complet - 2 Crédits (30 heures)
CM, TD, TP, TPE
1 - INTRODUCTION AUX CONCEPTS ORIENTÉS OBJETS
1.1- Définition
La Programmation Orientée Objet (POO) est un paradigme de programmation qui organise le code autour d’objets plutôt que de fonctions et de logique. Un objet combine données (attributs) et comportements (méthodes) dans une seule entité.
💡 Analogie de la vie réelle : Imaginez une voiture :
- Elle a des caractéristiques : couleur, marque, vitesse
- Elle a des comportements : démarrer, accélérer, freiner
- Elle cache sa complexité : vous n’avez pas besoin de savoir comment fonctionne le moteur pour conduire
Pourquoi la POO ?
Avant la POO (Programmation procédurale) :
- Code organisé en fonctions séparées
- Données et traitements séparés
- Difficile à maintenir sur de gros projets
- Risque de conflits de noms
- Code difficilement réutilisable
Avec la POO :
- Code organisé en objets autonomes
- Données et comportements liés ensemble
- Maintenance facilitée
- Pas de conflits (encapsulation)
- Réutilisation naturelle du code
1.2- Les Paradigmes de Programmation
Programmation Procédurale
<?php
declare(strict_types=1);
// Approche procédurale
$nom = "eva";
$age = 25;
$email = "eva@example.com";
function afficherUtilisateur($nom, $age, $email) {
echo "$nom, $age ans, $email";
}
function envoyerEmail($email, $message) {
// Envoyer email
}
afficherUtilisateur($nom, $age, $email);
envoyerEmail($email, "Bonjour");
?>
Problèmes :
- Les données traînent partout
- Aucun lien logique entre données et fonctions
- Difficile de savoir quelles fonctions utilisent quelles données
Programmation Orientée Objet
<?php
declare(strict_types=1);
// Approche POO
class Utilisateur {
private string $nom;
private int $age;
private string $email;
public function __construct(string $nom, int $age, string $email) {
$this->nom = $nom;
$this->age = $age;
$this->email = $email;
}
public function afficher(): void {
echo "{$this->nom}, {$this->age} ans, {$this->email}";
}
public function envoyerEmail(string $message): void {
// Envoyer email à $this->email
}
}
$eva = new Utilisateur("eva", 25, "eva@example.com");
$eva->afficher();
$eva->envoyerEmail("Bonjour");
Avantages :
- Tout ce qui concerne un utilisateur est dans la classe
Utilisateur - Les données sont protégées (private)
- Le code est organisé et logique
1.3- Concepts Fondamentaux de la POO
Les 4 Piliers de la POO
- Encapsulation : Regrouper données et méthodes, cacher les détails
- Abstraction : Simplifier la complexité en ne montrant que l’essentiel
- Héritage : Réutiliser du code d’une classe parente
- Polymorphisme : Même interface, comportements différents
Ou encore
| Pilier | Description | Exemple Réel |
|---|---|---|
| Encapsulation | Regrouper données et méthodes | Un téléphone cache ses circuits internes |
| Héritage | Créer à partir de l’existant | Une voiture électrique hérite des propriétés d’une voiture |
| Polymorphisme | Plusieurs formes | Un bouton “play” fonctionne pour musique, vidéo, etc. |
| Abstraction | Simplifier la complexité | Un volant = interface simple pour système complexe |
1.4- Exemple du Monde Réel : Une Voiture
Dans le monde réel :
- Une voiture est un objet physique
- Elle a des caractéristiques : couleur, marque, modèle, vitesse
- Elle a des comportements : démarrer, accélérer, freiner, klaxonner
Avantages de la POO
<?php
declare(strict_types=1);
// ❌ SANS POO - Code procédural désorganisé
$voiture1_marque: string = "Toyota";
$voiture1_vitesse: int = 0;
$voiture2_marque: string = "Peugeot";
$voiture2_vitesse: int = 0;
function accelerer_voiture(int &$vitesse, int $augmentation): void {
$vitesse += $augmentation;
}
// ✅ AVEC POO - Code organisé et réutilisable
class Voiture {
private string $marque;
private int $vitesse = 0;
public function __construct(string $marque) {
$this->marque = $marque;
}
public function accelerer(int $augmentation): void {
$this->vitesse += $augmentation;
}
}
$voiture1 = new Voiture("Toyota");
$voiture2 = new Voiture("Peugeot");
?>
1.5- Vocabulaire Essentiel
| Terme | Définition | Exemple |
|---|---|---|
| Classe | Modèle, plan, blueprint | class Voiture |
| Objet | Instance concrète d’une classe | $maVoiture = new Voiture() |
| Attribut | Variable dans une classe (caractéristique) | private string $couleur |
| Méthode | Fonction dans une classe (comportement) | public function demarrer() |
| Instance | Un objet créé à partir d’une classe | $voiture1, $voiture2 |
| Instanciation | Action de créer un objet | new Voiture() |
2 - OBJETS ET CLASSES
2.1- Définition d’une Classe
Une classe est un modèle (template) qui décrit :
- Les attributs (données) que les objets auront
- Les méthodes (comportements) que les objets pourront exécuter
🏗️ Classe : Un plan, un modèle, un moule pour créer des objets 📦 Objet : Une instance concrète créée à partir d’une classe 🔧 Attribut/Propriété : Une caractéristique de l’objet ⚡ Méthode : Une action que l’objet peut effectuer
💡 Analogie :
- Classe = Plan d’architecte d’une maison
- Objet = Maison construite selon ce plan
- Attributs = Nombre de chambres, couleur, surface
- Méthodes = Ouvrir la porte, allumer les lumières
Syntaxe PHP 8.4
<?php
declare(strict_types=1);
class NomDeLaClasse {
// Attributs (propriétés)
private type $attribut1;
protected type $attribut2;
public type $attribut3;
// Constructeur
public function __construct(parameters) {
// Initialisation
}
// Méthodes
public function nomMethode(parameters): returnType {
// Code
}
}
?>
Convention de Nommage
- Classe : PascalCase (
Utilisateur,CompteBancaire,VoitureElectrique) - Méthodes : camelCase (
calculerTotal,afficherDetails,envoyerEmail) - Attributs : camelCase (
$nom,$dateNaissance,$soldeCompte)
2.2 Définition d’un Objet
Un objet est une instance concrète d’une classe. C’est une entité qui existe en mémoire avec ses propres valeurs d’attributs.
Syntaxe
//Syntaxe
$nomVariable = new NomDeLaClasse(arguments);
Exemple Réel : Gestion d’Employés
<?php
declare(strict_types=1);
class Employe {
private string $nom;
private string $prenom;
private float $salaire;
private string $poste;
public function __construct(
string $nom,
string $prenom,
float $salaire,
string $poste
) {
$this->nom = $nom;
$this->prenom = $prenom;
$this->salaire = $salaire;
$this->poste = $poste;
}
public function afficherFiche(): void {
echo "===== FICHE EMPLOYÉ =====\n";
echo "Nom : {$this->nom}\n";
echo "Prénom : {$this->prenom}\n";
echo "Poste : {$this->poste}\n";
echo "Salaire : {$this->salaire} FCFA\n";
echo "========================\n";
}
public function augmenterSalaire(float $pourcentage): void {
$ancienSalaire = $this->salaire;
$this->salaire += ($this->salaire * $pourcentage / 100);
echo "{$this->prenom} : Augmentation de {$pourcentage}%\n";
echo "Ancien salaire : {$ancienSalaire} FCFA\n";
echo "Nouveau salaire : {$this->salaire} FCFA\n";
}
}
// Création d'objets (instances)
$employe1 = new Employe("Dupont", "eva", 2500, "Développeuse");
$employe2 = new Employe("Martin", "Bob", 3000, "Chef de projet");
$employe3 = new Employe("Durand", "Clara", 2200, "Designer");
// Utilisation
$employe1->afficherFiche();
$employe1->augmenterSalaire(10);
$employe2->afficherFiche();
?>
Sortie :
===== FICHE EMPLOYÉ =====
Nom : Dupont
Prénom : eva
Poste : Développeuse
Salaire : 2500 FCFA
========================
eva : Augmentation de 10%
Ancien salaire : 2500 FCFA
Nouveau salaire : 2750 FCFA
===== FICHE EMPLOYÉ =====
Nom : Martin
Prénom : Bob
Poste : Chef de projet
Salaire : 3000 FCFA
========================
Syntaxe de création d’objet
$nomVariable = new NomDeLaClasse(arguments);
new: Mot-clé pour créer une nouvelle instanceNomDeLaClasse: Le nom de la classe à instancierarguments: Paramètres passés au constructeur$nomVariable: Variable qui référence l’objet créé
Exemple Réel : Gestion d’Employés
La Classe Employe (Le plan)
class Employe {
private string $nom;
private string $prenom;
private float $salaire;
private string $poste;
Propriétés private : Données encapsulées (protégées), accessibles seulement via les méthodes de la classe.
Le Constructeur
public function __construct(
string $nom,
string $prenom,
float $salaire,
string $poste
) {
$this->nom = $nom;
$this->prenom = $prenom;
$this->salaire = $salaire;
$this->poste = $poste;
}
$this : Référence à l’objet courant. Permet d’accéder à ses propriétés et méthodes.
Méthode afficherFiche()
public function afficherFiche(): void {
echo "===== FICHE EMPLOYÉ =====\n";
echo "Nom : {$this->nom}\n";
echo "Prénom : {$this->prenom}\n";
echo "Poste : {$this->poste}\n";
echo "Salaire : {$this->salaire} FCFA\n";
echo "========================\n";
}
Affiche les informations de l’employé courant ($this).
Méthode augmenterSalaire()
public function augmenterSalaire(float $pourcentage): void {
$ancienSalaire = $this->salaire;
$this->salaire += ($this->salaire * $pourcentage / 100);
echo "{$this->prenom} : Augmentation de {$pourcentage}%\n";
echo "Ancien salaire : {$ancienSalaire} FCFA\n";
echo "Nouveau salaire : {$this->salaire} FCFA\n";
}
Modifie le salaire de l’employé spécifique sur lequel la méthode est appelée.
Création des Objets (Instances)
$employe1 = new Employe("Dupont", "eva", 2500, "Développeuse");
$employe2 = new Employe("Martin", "Bob", 3000, "Chef de projet");
$employe3 = new Employe("Durand", "Clara", 2200, "Designer");
3 objets distincts créés, chacun avec ses propres valeurs :
$employe1: Dupont Eva, 2500 FCFA, Développeuse$employe2: Martin Bob, 3000 FCFA, Chef de projet$employe3: Durand Clara, 2200 FCFA, Designer
Utilisation des Objets
$employe1->afficherFiche();
$employe1->augmenterSalaire(10);
$employe2->afficherFiche();
-> : Opérateur d’accès aux méthodes et propriétés d’un objet.
✅ Ce que démontre cet exemple :
- Encapsulation : Les données sont protégées (
private) - Abstraction : Interface simple (
afficherFiche(),augmenterSalaire()) - Indépendance : Chaque objet a son propre état
- Réutilisabilité : Même classe pour tous les employés
Résumé
| Concept | Explication |
|---|---|
| Classe | Plan/moule (Employe) |
| Objet | Instance concrète ($employe1, $employe2) |
new |
Crée une nouvelle instance |
$this |
Référence à l’objet courant |
-> |
Accède aux méthodes/propriétés |
Les objets permettent de modéliser le monde réel de manière organisée et maintenable ! 🚀
2.3 Attributs (Propriétés)
Les attributs sont des variables définies dans une classe qui représentent l’état d’un objet.
Types d’Attributs
<?php
declare(strict_types=1);
class Produit {
// Attributs avec types (PHP 8.4)
private string $nom; // Texte
private float $prix; // Nombre décimal
private int $quantite; // Nombre entier
private bool $enStock; // Vrai/Faux
private ?string $description; // Texte ou null
private array $categories; // Tableau
}
?>
Absolument ! Voici une explication détaillée uniquement des attributs de la classe Produit :
📊 Attributs de la Classe Produit
🔒 Visibilité private
Tous les attributs sont déclarés private :
- ✅ Encapsulation : Protection des données internes
- ✅ Contrôle d’accès : Accessibles seulement depuis la classe elle-même
- ✅ Sécurité : Empêche les modifications externes directes
Détail de chaque Attribut
private string $nom
- Type :
string(chaîne de caractères) - Contenu : Texte
- Usage : Nom du produit
- Exemple :
"Ordinateur Portable","Cafetière"
private float $prix
- Type :
float(nombre à virgule flottante) - Contenu : Nombre décimal
- Usage : Prix du produit
- Exemple :
299.99,15.50
private int $quantite
- Type :
int(entier) - Contenu : Nombre entier
- Usage : Quantité disponible en stock
- Exemple :
5,0,100
private bool $enStock
- Type :
bool(booléen) - Contenu : Vrai ou Faux
- Usage : Indique la disponibilité
- Exemple :
true(disponible),false(rupture)
private ?string $description
- Type :
?string(chaîne nullable) - Contenu : Texte ou
null - Usage : Description optionnelle
- Exemple :
"Écran 15 pouces, 8GB RAM"ounull
private array $categories
- Type :
array(tableau) - Contenu : Liste de valeurs
- Usage : Catégories du produit
- Exemple :
["électronique", "informatique"]
Points Importants
Typage Fort
- Chaque attribut a un type spécifique
- PHP vérifie le type lors des assignations
- Prévention des erreurs de type
Attribut Nullable
?string= peut êtrestringounull- Utile pour les données optionnelles
Attribut Booléen
$enStockreprésente un état binaire- Parfait pour les flags true/false
Attribut Tableau
$categoriespeut contenir multiple valeurs- Flexible pour les classifications multiples
Résumé des Types
| Attribut | Type | Contenu |
|---|---|---|
$nom |
string |
Texte |
$prix |
float |
Nombre décimal |
$quantite |
int |
Nombre entier |
$enStock |
bool |
Vrai/Faux |
$description |
?string |
Texte ou null |
$categories |
array |
Tableau |
En résumé : Ces attributs définissent parfaitement les caractéristiques essentielles d’un produit dans un système e-commerce !
La Pseudo-Variable $this
$this représente l’instance actuelle de l’objet.
<?php
declare(strict_types=1);
class CompteBancaire {
private float $solde;
public function __construct(float $soldeInitial) {
$this->solde = $soldeInitial; // $this = cet objet précis
}
public function deposer(float $montant): void {
$this->solde += $montant; // Accès à l'attribut de CET objet
}
public function retirer(float $montant): void {
if ($this->solde >= $montant) {
$this->solde -= $montant;
}
}
public function afficherSolde(): void {
echo "Solde : {$this->solde} FCFA\n";
}
}
$compte1 = new CompteBancaire(1000);
$compte2 = new CompteBancaire(500);
$compte1->deposer(200); // $this = $compte1
$compte2->retirer(100); // $this = $compte2
$compte1->afficherSolde(); // Solde : 1200 FCFA
$compte2->afficherSolde(); // Solde : 400 FCFA
?>
2.4 Méthodes
Les méthodes sont des fonctions définies dans une classe qui représentent les comportements d’un objet.
Syntaxe
<?php
declare(strict_types=1);
class NomClasse {
public function nomMethode(type $param): returnType {
// Code
return $resultat;
}
}
?>
Types de Méthodes
<?php
declare(strict_types=1);
class Calculatrice {
private float $resultat = 0;
// Méthode sans paramètres, sans retour
public function reset(): void {
$this->resultat = 0;
}
// Méthode avec paramètres, sans retour
public function ajouter(float $nombre): void {
$this->resultat += $nombre;
}
// Méthode avec paramètres et retour
public function multiplier(float $a, float $b): float {
return $a * $b;
}
// Méthode getter (retour simple)
public function obtenirResultat(): float {
return $this->resultat;
}
}
?>
Syntaxe Générale
public function nomMethode(type $param): returnType {
// Code
return $resultat;
}
public: Visibilité (accès)function: Mot-clé pour définir une méthodenomMethode: Nom de la méthode(type $param): Paramètres typés: returnType: Type de retourreturn: Valeur retournée
Types de Méthodes dans l’Exemple
Méthode sans paramètres, sans retour
public function reset(): void {
$this->resultat = 0;
}
void: Ne retourne aucune valeur- Action : Réinitialise l’état interne
- Usage : Modifie l’objet sans retourner de données
Méthode avec paramètres, sans retour
public function ajouter(float $nombre): void {
$this->resultat += $nombre;
}
- Paramètre :
float $nombre(nombre à ajouter) void: Pas de retour- Action : Modifie l’attribut
$resultat - Usage : Opération qui change l’état de l’objet
Méthode avec paramètres et retour
public function multiplier(float $a, float $b): float {
return $a * $b;
}
- Paramètres :
float $a,float $b(nombres à multiplier) - Retour :
float(résultat de la multiplication) - Action : Calcule et retourne un résultat
- Usage : Fonction utilitaire qui ne modifie pas l’objet
Méthode Getter (accesseur)
public function obtenirResultat(): float {
return $this->resultat;
}
- Aucun paramètre
- Retour :
float(valeur de l’attribut) - Action : Fournit l’accès à une propriété
private - Usage : Lecture sécurisée des données encapsulées
Points Clés
Encapsulation
- Les méthodes permettent d’accéder/modifier les attributs
private - Contrôle total sur les modifications des données
Typage Fort
- Paramètres typés :
float $nombre - Retour typé :
: float,: void - Prévention des erreurs de type
$this Mot-Clé
$thisréférence l’objet courant- Permet d’accéder aux attributs et méthodes de l’instance
Void vs Return
void: Méthode qui effectue une action sans retourreturn: Méthode qui calcule et retourne une valeur
Résumé des Types de Méthodes
| Type | Paramètres | Retour | Usage |
|---|---|---|---|
| Modificateur | Optionnels | void |
Modifie l’état |
| Accesseur | Aucun | Type | Lit les données |
| Utilitaire | Multiple | Type | Calcule et retourne |
En résumé : Les méthodes définissent ce que l’objet peut faire et comment interagir avec ses données ! 🚀
2.5 Constructeur
Le constructeur est une méthode spéciale appelée automatiquement lors de la création d’un objet. Il sert à initialiser les attributs.
Syntaxe Classique
<?php
declare(strict_types=1);
class Livre {
private string $titre;
private string $auteur;
private int $anneePublication;
public function __construct(string $titre, string $auteur, int $annee) {
$this->titre = $titre;
$this->auteur = $auteur;
$this->anneePublication = $annee;
}
}
$livre = new Livre("1984", "George Orwell", 1949);
?>
Constructor Property Promotion (PHP 8.0+)
Syntaxe moderne qui déclare et initialise en une ligne :
<?php
declare(strict_types=1);
class Livre {
public function __construct(
private string $titre,
private string $auteur,
private int $anneePublication
) {
// Rien à faire ! Les attributs sont déclarés et initialisés automatiquement
}
public function afficher(): void {
echo "{$this->titre} par {$this->auteur} ({$this->anneePublication})\n";
}
}
$livre1 = new Livre("1984", "George Orwell", 1949);
$livre2 = new Livre("Le Petit Prince", "Antoine de Saint-Exupéry", 1943);
$livre1->afficher();
$livre2->afficher();
?>
Caractéristiques :
- Nom :
__construct(méthode magique) - Appel automatique à l’instanciation avec
new - Initialise les attributs avec les valeurs fournies
- Paramètres typés pour la sécurité
Processus :
$livre = new Livre("1984", "George Orwell", 1949);
- Création de l’objet avec
new - Appel automatique de
__construct() - Assignation des valeurs aux attributs
🚀 Constructor Property Promotion (PHP 8.0+)
Syntaxe Moderne :
public function __construct(
private string $titre,
private string $auteur,
private int $anneePublication
) {
// Rien à faire ! Les attributs sont déclarés et initialisés automatiquement
}
Avantages :
- ✅ Déclaration + initialisation en une seule étape
- ✅ Code plus concis (moins de répétition)
- ✅ Maintenance simplifiée
- ✅ Modernité (PHP 8.0+)
Équivalence :
Ancienne syntaxe :
private string $titre;
private string $auteur;
private int $anneePublication;
public function __construct(string $titre, string $auteur, int $anneePublication) {
$this->titre = $titre;
$this->auteur = $auteur;
$this->anneePublication = $anneePublication;
}
Nouvelle syntaxe :
public function __construct(
private string $titre,
private string $auteur,
private int $anneePublication
) {}
Points Clés du Constructeur
Encapsulation :
- Initialise les attributs
privatede manière contrôlée - Garantit que l’objet est dans un état valide dès sa création
Typage Fort :
- Paramètres typés :
string $titre,int $annee - Prévention des erreurs dès l’instanciation
⚡ Obligation de fournir les valeurs :
// ✅ Correct :
$livre = new Livre("1984", "George Orwell", 1949);
// ❌ Erreur (paramètres manquants) :
$livre = new Livre(); // Erreur !
Différences entre les Deux Syntaxes
| Aspect | Syntaxe Classique | Property Promotion |
|---|---|---|
| Déclaration attributs | Séparée | Directe dans les paramètres |
| Initialisation | Manuelle avec $this-> |
Automatique |
| Lignes de code | Plus nombreuses | Réduites |
| PHP requis | 5.4+ | 8.0+ |
💡 Bonnes Pratiques
✅ Toujours typer les paramètres
public function __construct(
private string $titre,
private string $auteur,
private int $anneePublication
) {}
✅ Utiliser la promotion si possible (PHP 8.0+)
- Code plus lisible
- Moins d’erreurs potentielles
✅ Validation dans le constructeur (optionnel)
public function __construct(
private string $titre,
private string $auteur,
private int $anneePublication
) {
if ($anneePublication < 0) {
throw new InvalidArgumentException("L'année doit être positive");
}
}
En résumé : Le constructeur est indispensable pour créer des objets valides et bien initialisés !
2.6 Exemple Réel Complet : Système de Gestion de Bibliothèque
<?php
declare(strict_types=1);
class Livre {
public function __construct(
private string $isbn,
private string $titre,
private string $auteur,
private int $anneePublication,
private bool $disponible = true
) {}
public function emprunter(): bool {
if ($this->disponible) {
$this->disponible = false;
echo "✓ '{$this->titre}' emprunté avec succès.\n";
return true;
}
echo "✗ '{$this->titre}' n'est pas disponible.\n";
return false;
}
public function retourner(): void {
$this->disponible = true;
echo "✓ '{$this->titre}' retourné à la bibliothèque.\n";
}
public function afficherInfos(): void {
$statut = $this->disponible ? "Disponible" : "Emprunté";
echo "─────────────────────────\n";
echo "Titre : {$this->titre}\n";
echo "Auteur : {$this->auteur}\n";
echo "Année : {$this->anneePublication}\n";
echo "ISBN : {$this->isbn}\n";
echo "Statut : {$statut}\n";
echo "─────────────────────────\n";
}
}
// Utilisation
$livre1 = new Livre("978-2-07-036822-8", "1984", "George Orwell", 1949);
$livre2 = new Livre("978-2-07-061275-8", "Le Petit Prince", "A. de Saint-Exupéry", 1943);
$livre1->afficherInfos();
$livre1->emprunter();
$livre1->afficherInfos();
$livre1->emprunter(); // Déjà emprunté
$livre1->retourner();
$livre1->afficherInfos();
?>
Sortie :
─────────────────────────
Titre : 1984
Auteur : George Orwell
Année : 1949
ISBN : 978-2-07-036822-8
Statut : Disponible
─────────────────────────
✓ '1984' emprunté avec succès.
─────────────────────────
Titre : 1984
Auteur : George Orwell
Année : 1949
ISBN : 978-2-07-036822-8
Statut : Emprunté
─────────────────────────
✗ '1984' n'est pas disponible.
✓ '1984' retourné à la bibliothèque.
─────────────────────────
Titre : 1984
Auteur : George Orwell
Année : 1949
ISBN : 978-2-07-036822-8
Statut : Disponible
─────────────────────────
<?php
declare(strict_types=1);
// DÉCLARATION D'UNE CLASSE
class Personne {
// ATTRIBUTS (Propriétés)
public string $nom; // Public : accessible partout
private int $age; // Private : accessible uniquement dans la classe
protected string $adresse; // Protected : accessible dans la classe et ses enfants
// CONSTRUCTEUR - Méthode spéciale appelée à la création
public function __construct(string $nom, int $age, string $adresse) {
$this->nom = $nom; // $this représente l'objet actuel
$this->age = $age;
$this->adresse = $adresse;
}
// MÉTHODES - Actions de l'objet
public function sePresenter(): string {
return "Je m'appelle {$this->nom} et j'ai {$this->age} ans.";
}
public function vieillir(): void {
$this->age++;
}
// GETTER - Obtenir une valeur privée
public function getAge(): int {
return $this->age;
}
// SETTER - Modifier une valeur privée avec validation
public function setAge(int $nouvelAge): void {
if ($nouvelAge < 0 || $nouvelAge > 150) {
throw new InvalidArgumentException("Âge invalide");
}
$this->age = $nouvelAge;
}
}
// CRÉATION D'OBJETS (Instanciation)
$personne1 = new Personne("Alice", 25, "Bafoussam");
$personne2 = new Personne("Bob", 30, "Lyon");
// UTILISATION DES OBJETS
echo $personne1->sePresenter() . PHP_EOL; // Appel de méthode
echo "Nom : " . $personne1->nom . PHP_EOL; // Accès à propriété publique
// echo $personne1->age; // ERREUR ! age est privé
$personne1->vieillir();
echo "Nouvel âge : " . $personne1->getAge() . PHP_EOL;
?>
2.3 Exemple concret : Système Bancaire
<?php
declare(strict_types=1);
class CompteBancaire {
// Propriétés
private string $numero;
private string $titulaire;
private float $solde;
private array $historique = [];
// PHP 8.1+ : propriété readonly (ne peut être modifiée après initialisation)
public readonly DateTime $dateOuverture;
// Constructeur
public function __construct(string $titulaire, float $depotInitial = 0) {
$this->numero = $this->genererNumero();
$this->titulaire = $titulaire;
$this->solde = $depotInitial;
$this->dateOuverture = new DateTime();
if ($depotInitial > 0) {
$this->ajouterHistorique("Ouverture avec dépôt", $depotInitial);
}
}
// Méthode privée (utilisée uniquement en interne)
private function genererNumero(): string {
return 'CB' . date('Y') . rand(10000, 99999);
}
private function ajouterHistorique(string $operation, float $montant): void {
$this->historique[] = [
'date' => new DateTime(),
'operation' => $operation,
'montant' => $montant,
'solde' => $this->solde
];
}
// Méthodes publiques (interface de la classe)
public function deposer(float $montant): void {
if ($montant <= 0) {
throw new InvalidArgumentException("Le montant doit être positif");
}
$this->solde += $montant;
$this->ajouterHistorique("Dépôt", $montant);
echo "✅ Dépôt de {$montant}FCFA effectué\n";
}
public function retirer(float $montant): bool {
if ($montant <= 0) {
throw new InvalidArgumentException("Le montant doit être positif");
}
if ($montant > $this->solde) {
echo "❌ Solde insuffisant\n";
return false;
}
$this->solde -= $montant;
$this->ajouterHistorique("Retrait", -$montant);
echo "✅ Retrait de {$montant}FCFA effectué\n";
return true;
}
public function consulterSolde(): float {
return $this->solde;
}
public function afficherReleve(): void {
echo "\n=== RELEVÉ DE COMPTE ===\n";
echo "Compte N° : {$this->numero}\n";
echo "Titulaire : {$this->titulaire}\n";
echo "Solde actuel : {$this->solde}FCFA\n";
echo "\nDernières opérations :\n";
foreach (array_slice($this->historique, -5) as $op) {
printf(" %s - %s : %+.2fFCFA (Solde: %.2fFCFA)\n",
$op['date']->format('d/m/Y H:i'),
$op['operation'],
$op['montant'],
$op['solde']
);
}
}
}
// Utilisation
$compte = new CompteBancaire("Jean Dupont", 1000);
$compte->deposer(500);
$compte->retirer(200);
$compte->retirer(2000); // Échec
$compte->afficherReleve();
?>
3 - ENCAPSULATION ET MASQUAGE D’INFORMATION
3.1 Définition de l’Encapsulation
L’encapsulation est le principe de regrouper les données (attributs) et les comportements (méthodes) dans une même classe, et de contrôler l’accès à ces données.
Les 3 Objectifs de l’Encapsulation
- Protection des données : Empêcher la modification non contrôlée
- Cohérence : Garantir que l’état de l’objet reste valide
- Abstraction : Cacher la complexité interne
Ou encore :
Encapsulation : Mécanisme qui consiste à :
- Regrouper les données et les méthodes dans une classe
- Cacher les détails d’implémentation
- Contrôler l’accès aux données
💡 Analogie : Un distributeur automatique
- Vous voyez les boutons (interface publique)
- Vous ne voyez pas les mécanismes internes (implémentation privée)
- Vous interagissez uniquement via les boutons
3.2.1- Les Niveaux de Visibilité PHP
PHP propose 3 niveaux de visibilité :
| Visibilité | Accès depuis la classe | Accès depuis les enfants | Accès depuis l’extérieur |
|---|---|---|---|
private |
✅ Oui | ❌ Non | ❌ Non |
protected |
✅ Oui | ✅ Oui | ❌ Non |
public |
✅ Oui | ✅ Oui | ✅ Oui |
3.2.2- Niveaux d’accès
| Modificateur | PHP | C++ | Java | Description |
|---|---|---|---|---|
| Public | public | public | public | Accessible partout |
| Private | private | private | private | Accessible uniquement dans la classe |
| Protected | protected | protected | protected | Accessible dans la classe et ses dérivées |
| Package | - | - | (défaut) | Accessible dans le package |
Syntaxe
<?php
declare(strict_types=1);
class Exemple {
private string $attributPrive; // Accessible uniquement dans cette classe
protected string $attributProtege; // Accessible dans cette classe et ses enfants
public string $attributPublic; // Accessible partout
private function methodePrive(): void {}
protected function methodeProtegee(): void {}
public function methodePublic(): void {}
}
?>
3.3 Pourquoi Masquer l’Information ?
Exemple Sans Encapsulation (Mauvais)
<?php
declare(strict_types=1);
class CompteBancaire {
public float $solde; // Public = DANGER !
public function __construct(float $soldeInitial) {
$this->solde = $soldeInitial;
}
}
$compte = new CompteBancaire(1000);
// PROBLÈME : N'importe qui peut modifier directement !
$compte->solde = -5000; // Solde négatif impossible dans la réalité
$compte->solde = 999999999; // Fraude possible
echo "Solde : {$compte->solde} FCFA\n"; // Solde : 999999999 FCFA
?>
Problèmes :
- Aucun contrôle sur les valeurs
- Impossible de valider
- Incohérence possible
Exemple Avec Encapsulation (Bon)
<?php
declare(strict_types=1);
class CompteBancaire {
private float $solde; // Private = Protégé
public function __construct(float $soldeInitial) {
if ($soldeInitial < 0) {
throw new InvalidArgumentException("Le solde initial ne peut pas être négatif");
}
$this->solde = $soldeInitial;
}
public function deposer(float $montant): void {
if ($montant <= 0) {
throw new InvalidArgumentException("Le montant doit être positif");
}
$this->solde += $montant;
echo "✓ Dépôt de {$montant} FCFA effectué.\n";
}
public function retirer(float $montant): bool {
if ($montant <= 0) {
throw new InvalidArgumentException("Le montant doit être positif");
}
if ($this->solde < $montant) {
echo "✗ Solde insuffisant. Opération refusée.\n";
return false;
}
$this->solde -= $montant;
echo "✓ Retrait de {$montant} FCFA effectué.\n";
return true;
}
public function obtenirSolde(): float {
return $this->solde;
}
}
$compte = new CompteBancaire(1000);
// Maintenant, toutes les opérations sont contrôlées
$compte->deposer(500); // ✓ Dépôt de 500 FCFA effectué.
$compte->retirer(200); // ✓ Retrait de 200 FCFA effectué.
$compte->retirer(2000); // ✗ Solde insuffisant. Opération refusée.
// $compte->solde = 999999; // ERREUR : Cannot access private property
echo "Solde actuel : {$compte->obtenirSolde()} FCFA\n"; // Solde actuel : 1300 FCFA
?>
Avantages :
- Contrôle total sur les modifications
- Validation automatique
- Cohérence garantie
- Sécurité renforcée
3.4- Getters et Setters
Les getters et setters sont des méthodes publiques qui permettent de lire (get) et modifier (set) les attributs privés de manière contrôlée.
Syntaxe Classique
<?php
declare(strict_types=1);
class Personne {
private string $nom;
private int $age;
// Getter pour $nom
public function getNom(): string {
return $this->nom;
}
// Setter pour $nom
public function setNom(string $nom): void {
if (strlen($nom) < 2) {
throw new InvalidArgumentException("Le nom doit contenir au moins 2 caractères");
}
$this->nom = $nom;
}
// Getter pour $age
public function getAge(): int {
return $this->age;
}
// Setter pour $age avec validation
public function setAge(int $age): void {
if ($age < 0 || $age > 150) {
throw new InvalidArgumentException("Âge invalide");
}
$this->age = $age;
}
}
$personne = new Personne();
$personne->setNom("eva"); // ✓ Valide
$personne->setAge(25); // ✓ Valide
// $personne->setNom("A"); // ✗ Exception : Le nom doit contenir au moins 2 caractères
// $personne->setAge(200); // ✗ Exception : Âge invalide
echo $personne->getNom(); // eva
echo $personne->getAge(); // 25
?>
3.5- Property Hooks (PHP 8.4)
Nouveauté PHP 8.4 : Alternative moderne aux getters/setters.
Syntaxe
<?php
declare(strict_types=1);
class Personne {
public string $nom {
get => strtoupper($this->nom); // Lecture : toujours en majuscules
set => trim($value) ?: throw new ValueError("Nom vide"); // Écriture : validée
}
public int $age {
set {
if ($value < 0 || $value > 150) {
throw new ValueError("Âge invalide");
}
$this->age = $value;
}
}
}
$personne = new Personne();
$personne->nom = " eva "; // Trim automatique
echo $personne->nom; // eva (majuscules automatiques)
$personne->age = 25; // ✓ OK
// $personne->age = 200; // ✗ Exception : Âge invalide
?>
3.6- Asymmetric Visibility (PHP 8.4)
Nouveauté PHP 8.4 : Visibilité différente pour lecture et écriture.
Syntaxe
<?php
declare(strict_types=1);
class Utilisateur {
// Lecture : publique
// Écriture : privée
public private(set) string $email;
public private(set) string $motDePasseHash;
public function __construct(string $email, string $motDePasse) {
$this->email = $email;
$this->motDePasseHash = password_hash($motDePasse, PASSWORD_DEFAULT);
}
public function changerMotDePasse(string $ancienMotDePasse, string $nouveauMotDePasse): void {
if (!password_verify($ancienMotDePasse, $this->motDePasseHash)) {
throw new Exception("Mot de passe incorrect");
}
$this->motDePasseHash = password_hash($nouveauMotDePasse, PASSWORD_DEFAULT);
}
}
$user = new Utilisateur("eva@example.com", "secret123");
// Lecture : OK (public)
echo $user->email; // eva@example.com
// Écriture : ERREUR (private)
// $user->email = "hacker@evil.com"; // Cannot modify private(set) property
// Modification uniquement via méthode contrôlée
$user->changerMotDePasse("secret123", "newpassword456");
?>
3.7- Exemple Réel : Gestion de Stock de Produits
<?php
declare(strict_types=1);
class Produit {
private string $reference;
private string $nom;
private float $prixHT;
private int $stock;
private const TVA = 0.20; // 20%
public function __construct(string $ref, string $nom, float $prixHT, int $stockInitial) {
$this->reference = $ref;
$this->setNom($nom);
$this->setPrixHT($prixHT);
$this->stock = max(0, $stockInitial);
}
// Getter simple
public function getReference(): string {
return $this->reference;
}
public function getNom(): string {
return $this->nom;
}
// Setter avec validation
public function setNom(string $nom): void {
if (strlen($nom) < 3) {
throw new InvalidArgumentException("Le nom doit contenir au moins 3 caractères");
}
$this->nom = $nom;
}
public function getPrixHT(): float {
return $this->prixHT;
}
public function setPrixHT(float $prix): void {
if ($prix <= 0) {
throw new InvalidArgumentException("Le prix doit être positif");
}
$this->prixHT = $prix;
}
// Getter calculé
public function getPrixTTC(): float {
return $this->prixHT * (1 + self::TVA);
}
public function getStock(): int {
return $this->stock;
}
// Méthodes métier avec validation
public function ajouterStock(int $quantite): void {
if ($quantite <= 0) {
throw new InvalidArgumentException("La quantité doit être positive");
}
$this->stock += $quantite;
echo "✓ {$quantite} unités ajoutées. Stock : {$this->stock}\n";
}
public function vendre(int $quantite): bool {
if ($quantite <= 0) {
throw new InvalidArgumentException("La quantité doit être positive");
}
if ($this->stock < $quantite) {
echo "✗ Stock insuffisant ({$this->stock} disponibles)\n";
return false;
}
$this->stock -= $quantite;
$prixTotal = $this->getPrixTTC() * $quantite;
echo "✓ Vente de {$quantite} unités. Total : {$prixTotal} FCFA TTC\n";
echo " Stock restant : {$this->stock}\n";
return true;
}
public function afficherFiche(): void {
echo "\n═══════════════════════════════\n";
echo "Référence : {$this->reference}\n";
echo "Nom : {$this->nom}\n";
echo "Prix HT : {$this->prixHT} FCFA\n";
echo "Prix TTC : {$this->getPrixTTC()} FCFA\n";
echo "Stock : {$this->stock} unités\n";
echo "═══════════════════════════════\n";
}
}
// Utilisation
$produit = new Produit("REF-001", "Laptop Dell XPS", 1200, 50);
$produit->afficherFiche();
$produit->ajouterStock(10);
$produit->vendre(5);
$produit->vendre(100); // Stock insuffisant
$produit->afficherFiche();
// Tentative de modification directe : ERREUR
// $produit->stock = 1000; // Cannot access private property
?>
Sortie :
═══════════════════════════════
Référence : REF-001
Nom : Laptop Dell XPS
Prix HT : 1200 FCFA
Prix TTC : 1440 FCFA
Stock : 50 unités
═══════════════════════════════
✓ 10 unités ajoutées. Stock : 60
✓ Vente de 5 unités. Total : 7200 FCFA TTC
Stock restant : 55
✗ Stock insuffisant (55 disponibles)
═══════════════════════════════
Référence : REF-001
Nom : Laptop Dell XPS
Prix HT : 1200 FCFA
Prix TTC : 1440 FCFA
Stock : 55 unités
═══════════════════════════════
4 - AGRÉGATION ET DÉCOMPOSITION
Définitions et Différences
- 🔗 Association : Relation entre classes
- 📎 Agrégation : Relation “utilise” ou “a un” (faible)
- 🔧 Composition : Relation “fait partie de” (forte)
| Aspect | Agrégation | Composition |
|---|---|---|
| Dépendance | Faible | Forte |
| Cycle de vie | Indépendant | Dépendant |
| Exemple | École ← → Professeur | Voiture ← → Moteur |
| Symbole UML | Losange vide ◇ | Losange plein ◆ |
4.1- Définition de la Composition
La composition est une relation “a-un” (has-a) entre deux classes. Un objet contient d’autres objets comme parties de son état.
Types de Relations
- Composition : L’objet contenu n’existe pas sans son conteneur (dépendance forte)
- Agrégation : L’objet contenu peut exister indépendamment (dépendance faible)
4.2- Composition (Dépendance Forte)
Définition : L’objet contenu est créé et détruit avec son conteneur.
Exemple Réel : Voiture et Moteur
Une voiture a un moteur. Si la voiture est détruite, le moteur l’est aussi.
<?php
declare(strict_types=1);
class Moteur {
public function __construct(
private string $type,
private int $puissance,
private int $cylindree
) {}
public function demarrer(): void {
echo "Moteur {$this->type} ({$this->cylindree}cc, {$this->puissance}ch) : Vroum !\n";
}
public function afficherCaracteristiques(): void {
echo " - Type : {$this->type}\n";
echo " - Puissance : {$this->puissance} ch\n";
echo " - Cylindrée : {$this->cylindree} cc\n";
}
}
class Voiture {
private Moteur $moteur; // Composition : la voiture POSSÈDE un moteur
public function __construct(
private string $marque,
private string $modele,
string $typeMoteur,
int $puissance,
int $cylindree
) {
// Le moteur est créé EN MÊME TEMPS que la voiture
$this->moteur = new Moteur($typeMoteur, $puissance, $cylindree);
}
public function demarrer(): void {
echo "{$this->marque} {$this->modele} démarre...\n";
$this->moteur->demarrer();
}
public function afficherDetails(): void {
echo "\n╔═══════════════════════════════╗\n";
echo " {$this->marque} {$this->modele}\n";
echo "╠═══════════════════════════════╣\n";
echo "Caractéristiques du moteur :\n";
$this->moteur->afficherCaracteristiques();
echo "╚═══════════════════════════════╝\n";
}
}
// Utilisation
$voiture = new Voiture("BMW", "M3", "V6 Essence", 510, 2993);
$voiture->demarrer();
$voiture->afficherDetails();
// Le moteur n'existe PAS indépendamment de la voiture
// On ne peut pas créer le moteur séparément puis l'attacher
?>
Sortie :
BMW M3 démarre...
Moteur V6 Essence (2993cc, 510ch) : Vroum !
╔═══════════════════════════════╗
BMW M3
╠═══════════════════════════════╣
Caractéristiques du moteur :
- Type : V6 Essence
- Puissance : 510 ch
- Cylindrée : 2993 cc
╚═══════════════════════════════╝
4.3- Agrégation (Dépendance Faible)
Définition : L’objet contenu existe indépendamment de son conteneur.
Exemple Réel : Université et Étudiants
Une université a des étudiants. Si l’université ferme, les étudiants continuent d’exister.
<?php
declare(strict_types=1);
class Etudiant {
public function __construct(
private string $matricule,
private string $nom,
private string $prenom,
private string $niveau
) {}
public function getMatricule(): string {
return $this->matricule;
}
public function afficher(): void {
echo " • {$this->matricule} - {$this->prenom} {$this->nom} ({$this->niveau})\n";
}
}
class Universite {
private array $etudiants = [];
public function __construct(
private string $nom,
private string $ville
) {}
// Les étudiants sont AJOUTÉS (pas créés par l'université)
public function inscrireEtudiant(Etudiant $etudiant): void {
$this->etudiants[$etudiant->getMatricule()] = $etudiant;
echo "✓ Étudiant inscrit à {$this->nom}\n";
}
public function desinscrireEtudiant(string $matricule): void {
if (isset($this->etudiants[$matricule])) {
unset($this->etudiants[$matricule]);
echo "✓ Étudiant désinscrit de {$this->nom}\n";
}
}
public function afficherEtudiants(): void {
echo "\n╔═══════════════════════════════════════╗\n";
echo " {$this->nom} - {$this->ville}\n";
echo "╠═══════════════════════════════════════╣\n";
echo "Étudiants inscrits ({$this->compterEtudiants()}) :\n";
if (empty($this->etudiants)) {
echo " Aucun étudiant inscrit.\n";
} else {
foreach ($this->etudiants as $etudiant) {
$etudiant->afficher();
}
}
echo "╚═══════════════════════════════════════╝\n";
}
public function compterEtudiants(): int {
return count($this->etudiants);
}
}
// Les étudiants existent AVANT l'université
$etudiant1 = new Etudiant("E001", "Dupont", "eva", "Licence 3");
$etudiant2 = new Etudiant("E002", "Martin", "Bob", "Master 1");
$etudiant3 = new Etudiant("E003", "Durand", "Clara", "Licence 2");
// L'université les agrège
$universite = new Universite("L'Ecole Supérieure la Canadienne", "Bafoussam");
$universite->inscrireEtudiant($etudiant1);
$universite->inscrireEtudiant($etudiant2);
$universite->inscrireEtudiant($etudiant3);
$universite->afficherEtudiants();
$universite->desinscrireEtudiant("E002");
$universite->afficherEtudiants();
// Les étudiants existent toujours après désinscription
echo "\nÉtudiant 2 existe toujours :\n";
$etudiant2->afficher();
?>
Sortie :
✓ Étudiant inscrit à L'Ecole Supérieure la Canadienne
✓ Étudiant inscrit à L'Ecole Supérieure la Canadienne
✓ Étudiant inscrit à L'Ecole Supérieure la Canadienne
╔═══════════════════════════════════════╗
L'Ecole Supérieure la Canadienne - Bafoussam
╠═══════════════════════════════════════╣
Étudiants inscrits (3) :
• E001 - Eva Myra (Licence 3)
• E002 - Sohan Owen (Master 1)
• E003 - Diane rosto (Licence 2)
╚═══════════════════════════════════════╝
✓ Étudiant désinscrit de L'Ecole Supérieure la Canadienne
╔═══════════════════════════════════════╗
L'Ecole Supérieure la Canadienne - Bafoussam
╠═══════════════════════════════════════╣
Étudiants inscrits (2) :
• E001 - Eva Myra (Licence 3)
• E003 - Diane rosto (Licence 2)
╚═══════════════════════════════════════╝
Étudiant 2 existe toujours :
• E002 - Sohan Owen (Master 1)
4.4- Décomposition en Classes
Principe : Diviser un système complexe en classes plus simples et cohésives.
Exemple Réel : Système de Commande E-commerce
<?php
declare(strict_types=1);
class Produit {
public function __construct(
private string $reference,
private string $nom,
private float $prix
) {}
public function getReference(): string { return $this->reference; }
public function getNom(): string { return $this->nom; }
public function getPrix(): float { return $this->prix; }
}
class LigneCommande {
public function __construct(
private Produit $produit,
private int $quantite
) {}
public function calculerSousTotal(): float {
return $this->produit->getPrix() * $this->quantite;
}
public function afficher(): void {
$sousTotal = $this->calculerSousTotal();
echo " • {$this->produit->getNom()} x{$this->quantite} = {$sousTotal} FCFA\n";
}
}
class Adresse {
public function __construct(
private string $rue,
private string $ville,
private string $codePostal,
private string $pays
) {}
public function afficher(): void {
echo "{$this->rue}, {$this->codePostal} {$this->ville}, {$this->pays}";
}
}
class Client {
public function __construct(
private string $nom,
private string $prenom,
private string $email,
private Adresse $adresse
) {}
public function getNomComplet(): string {
return "{$this->prenom} {$this->nom}";
}
public function getEmail(): string {
return $this->email;
}
public function afficherAdresse(): void {
$this->adresse->afficher();
}
}
class Commande {
private array $lignes = [];
private string $numero;
private DateTime $date;
public function __construct(
private Client $client
) {
$this->numero = "CMD-" . uniqid();
$this->date = new DateTime();
}
public function ajouterLigne(Produit $produit, int $quantite): void {
$ligne = new LigneCommande($produit, $quantite);
$this->lignes[] = $ligne;
echo "✓ Produit ajouté à la commande\n";
}
public function calculerTotal(): float {
$total = 0;
foreach ($this->lignes as $ligne) {
$total += $ligne->calculerSousTotal();
}
return $total;
}
public function afficherFacture(): void {
echo "\n╔════════════════════════════════════════════╗\n";
echo " FACTURE\n";
echo "╠════════════════════════════════════════════╣\n";
echo "Commande N° : {$this->numero}\n";
echo "Date : {$this->date->format('d/m/Y H:i')}\n";
echo "\n";
echo "Client : {$this->client->getNomComplet()}\n";
echo "Email : {$this->client->getEmail()}\n";
echo "Adresse : ";
$this->client->afficherAdresse();
echo "\n";
echo "╠════════════════════════════════════════════╣\n";
echo "Détail de la commande :\n";
foreach ($this->lignes as $ligne) {
$ligne->afficher();
}
echo "╠════════════════════════════════════════════╣\n";
echo "TOTAL : {$this->calculerTotal()} FCFA\n";
echo "╚════════════════════════════════════════════╝\n";
}
}
// Utilisation
$adresse = new Adresse("123 Rue de la Paix", "Bafoussam", "75002", "France");
$client = new Client("Dupont", "eva", "eva@example.com", $adresse);
$produit1 = new Produit("P001", "Laptop Dell XPS", 1200);
$produit2 = new Produit("P002", "Souris Logitech", 45);
$produit3 = new Produit("P003", "Clavier mécanique", 150);
$commande = new Commande($client);
$commande->ajouterLigne($produit1, 1);
$commande->ajouterLigne($produit2, 2);
$commande->ajouterLigne($produit3, 1);
$commande->afficherFacture();
?>
Sortie :
✓ Produit ajouté à la commande
✓ Produit ajouté à la commande
✓ Produit ajouté à la commande
╔════════════════════════════════════════════╗
FACTURE
╠════════════════════════════════════════════╣
Commande N° : CMD-67abc123def
Date : 26/10/2025 14:30
Client : Eva Myra
Email : eva@example.com
Adresse : 123 Rue de la Paix, 75002 Bafoussam, France
╠════════════════════════════════════════════╣
Détail de la commande :
• Laptop Dell XPS x1 = 1200 FCFA
• Souris Logitech x2 = 90 FCFA
• Clavier mécanique x1 = 150 FCFA
╠════════════════════════════════════════════╣
TOTAL : 1440 FCFA
╚════════════════════════════════════════════╝
Avantages de la décomposition :
- Chaque classe a une responsabilité unique
- Code modulaire et réutilisable
- Maintenance facilitée
- Tests plus simples
5- GÉNÉRALISATION ET SPÉCIALISATION
5.1- Définition
- Généralisation : Identifier les caractéristiques communes de plusieurs classes et les regrouper dans une classe parente (classe de base)
- Spécialisation : Créer des classes enfants qui ajoutent des comportements spécifiques
5.2- Le Concept
Analogie du Monde Réel : Les Animaux
Observation :
- Un chien, un chat et un oiseau sont tous des animaux
- Tous ont un nom, un âge
- Tous peuvent manger, dormir
- Mais chacun a des comportements spécifiques :
- Le chien aboie
- Le chat miaule
- L’oiseau vole
Solution POO :
- Généralisation : Créer une classe
Animalavec les caractéristiques communes - Spécialisation : Créer des classes
Chien,Chat,Oiseauqui héritent deAnimal
5.3 Hiérarchie de Classes
Animal (classe parente générale)
|
┌───────┼───────┐
| | |
Chien Chat Oiseau (classes enfants spécialisées)
Exemple Sans Généralisation (Répétition)
<?php
declare(strict_types=1);
// MAUVAISE APPROCHE : Répétition de code
class Chien {
private string $nom;
private int $age;
public function manger(): void {
echo "{$this->nom} mange.\n";
}
public function dormir(): void {
echo "{$this->nom} dort.\n";
}
public function aboyer(): void {
echo "{$this->nom} : Woof woof !\n";
}
}
class Chat {
private string $nom; // RÉPÉTITION
private int $age; // RÉPÉTITION
public function manger(): void { // RÉPÉTITION
echo "{$this->nom} mange.\n";
}
public function dormir(): void { // RÉPÉTITION
echo "{$this->nom} dort.\n";
}
public function miauler(): void {
echo "{$this->nom} : Miaou !\n";
}
}
// Beaucoup de code dupliqué !
?>
5.4- Exemple Avec Généralisation
<?php
declare(strict_types=1);
// Classe parente GÉNÉRALE
class Animal {
public function __construct(
protected string $nom, // protected = accessible dans les enfants
protected int $age
) {}
// Comportements COMMUNS à tous les animaux
public function manger(): void {
echo "{$this->nom} mange.\n";
}
public function dormir(): void {
echo "{$this->nom} dort.\n";
}
public function afficherInfos(): void {
echo "Animal : {$this->nom}, {$this->age} ans\n";
}
}
// Classes enfants SPÉCIALISÉES
class Chien extends Animal {
// Comportement SPÉCIFIQUE au chien
public function aboyer(): void {
echo "{$this->nom} : Woof woof !\n";
}
}
class Chat extends Animal {
// Comportement SPÉCIFIQUE au chat
public function miauler(): void {
echo "{$this->nom} : Miaou !\n";
}
}
class Oiseau extends Animal {
// Comportement SPÉCIFIQUE à l'oiseau
public function voler(): void {
echo "{$this->nom} vole dans le ciel.\n";
}
}
// Utilisation
$chien = new Chien("Rex", 3);
$chat = new Chat("Whiskers", 2);
$oiseau = new Oiseau("Tweety", 1);
// Comportements communs (hérités)
$chien->manger();
$chat->dormir();
$oiseau->afficherInfos();
// Comportements spécifiques
$chien->aboyer();
$chat->miauler();
$oiseau->voler();
?>
Sortie :
Rex mange.
Whiskers dort.
Animal : Tweety, 1 ans
Rex : Woof woof !
Whiskers : Miaou !
Tweety vole dans le ciel.
5.5- Exemple Réel : Système de Gestion d’Employés
<?php
declare(strict_types=1);
// Classe GÉNÉRALE : Employé - PHP 8.3+
class Employe {
public function __construct(
protected string $matricule,
protected string $nom,
protected string $prenom,
protected float $salaireBase
) {}
// Méthode commune
public function afficherFiche(): void {
echo "\n┌─────────────────────────────┐\n";
echo "│ Matricule : {$this->matricule}\n";
echo "│ Nom : {$this->prenom} {$this->nom}\n";
echo "│ Salaire : {$this->calculerSalaire()} FCFA\n";
echo "└─────────────────────────────┘\n";
}
// Méthode de base (sera redéfinie dans les enfants)
public function calculerSalaire(): float {
return $this->salaireBase;
}
}
// Classe SPÉCIALISÉE : Développeur
class Developpeur extends Employe {
public function __construct(
string $matricule,
string $nom,
string $prenom,
float $salaireBase,
private string $langage,
private int $anneesExperience
) {
parent::__construct($matricule, $nom, $prenom, $salaireBase);
}
// REDÉFINITION : calcul spécifique
public function calculerSalaire(): float {
$bonus = $this->anneesExperience * 100;
return $this->salaireBase + $bonus;
}
// Méthode SPÉCIFIQUE
public function coder(): void {
echo "{$this->prenom} code en {$this->langage}...\n";
}
}
// Classe SPÉCIALISÉE : Manager
class Manager extends Employe {
public function __construct(
string $matricule,
string $nom,
string $prenom,
float $salaireBase,
private int $nombreSubordonnes
) {
parent::__construct($matricule, $nom, $prenom, $salaireBase);
}
// REDÉFINITION : calcul spécifique
public function calculerSalaire(): float {
$prime = $this->nombreSubordonnes * 200;
return $this->salaireBase + $prime;
}
// Méthode SPÉCIFIQUE
public function organiserReunion(): void {
echo "{$this->prenom} organise une réunion avec {$this->nombreSubordonnes} personnes.\n";
}
}
// Classe SPÉCIALISÉE : Commercial
class Commercial extends Employe {
public function __construct(
string $matricule,
string $nom,
string $prenom,
float $salaireBase,
private float $chiffreAffaires
) {
parent::__construct($matricule, $nom, $prenom, $salaireBase);
}
// REDÉFINITION : calcul spécifique
public function calculerSalaire(): float {
$commission = $this->chiffreAffaires * 0.05; // 5% de commission
return $this->salaireBase + $commission;
}
// Méthode SPÉCIFIQUE
public function prospecter(): void {
echo "{$this->prenom} contacte des clients potentiels.\n";
}
}
// Utilisation
$dev = new Developpeur("D001", "Dupont", "eva", 3000, "PHP", 5);
$manager = new Manager("M001", "Martin", "Bob", 4000, 10);
$commercial = new Commercial("C001", "Durand", "Clara", 2500, 50000);
$dev->afficherFiche();
$dev->coder();
$manager->afficherFiche();
$manager->organiserReunion();
$commercial->afficherFiche();
$commercial->prospecter();
?>
Sortie :
┌─────────────────────────────┐
│ Matricule : D001
│ Nom : Eva Myra
│ Salaire : 3500 FCFA
└─────────────────────────────┘
eva code en PHP...
┌─────────────────────────────┐
│ Matricule : M001
│ Nom : Sohan Owen
│ Salaire : 6000 FCFA
└─────────────────────────────┘
Bob organise une réunion avec 10 personnes.
┌─────────────────────────────┐
│ Matricule : C001
│ Nom : Diane rosto
│ Salaire : 5000 FCFA
└─────────────────────────────┘
Clara contacte des clients potentiels.
6- HÉRITAGE
6.1- Définition et Types
L’héritage est un mécanisme qui permet à une classe (classe enfant) de réutiliser les attributs et méthodes d’une autre classe (classe parente).
Relation “EST-UN” (is-a)
- Un Chien EST UN Animal
- Un Développeur EST UN Employé
- Une Voiture EST UN Véhicule
Types d’héritage :
- Simple : Une classe hérite d’une seule classe parent
- Multiple : Une classe hérite de plusieurs classes (non supporté en PHP)
- Multiniveau : A → B → C (chaîne d’héritage)
- Hiérarchique : Plusieurs classes héritent d’une même classe parent
6.2- Syntaxe de l’Héritage
<?php
declare(strict_types=1);
class ClasseParente {
// Code de la classe parente
}
class ClasseEnfant extends ClasseParente {
// Code de la classe enfant
// + hérite de tout le code de la classe parente
}
?>
6.3- Le Mot-clé parent
Le mot-clé parent:: permet d’accéder aux méthodes et constantes de la classe parente.
<?php
declare(strict_types=1);
class Vehicule {
public function __construct(
protected string $marque,
protected int $vitesseMax
) {
echo "Création d'un véhicule {$this->marque}\n";
}
public function demarrer(): void {
echo "Le véhicule démarre.\n";
}
}
class Voiture extends Vehicule {
public function __construct(
string $marque,
int $vitesseMax,
private int $nombrePortes
) {
// Appel du constructeur parent
parent::__construct($marque, $vitesseMax);
echo "C'est une voiture à {$this->nombrePortes} portes.\n";
}
public function demarrer(): void {
// Appel de la méthode parente
parent::demarrer();
echo "Contact, clé tournée, moteur lancé !\n";
}
public function ouvrirCoffre(): void {
echo "Coffre ouvert.\n";
}
}
$voiture = new Voiture("Peugeot", 180, 5);
$voiture->demarrer();
$voiture->ouvrirCoffre();
?>
Sortie :
Création d'un véhicule Peugeot
C'est une voiture à 5 portes.
Le véhicule démarre.
Contact, clé tournée, moteur lancé !
Coffre ouvert.
6.4- Redéfinition de Méthodes (Override)
Une classe enfant peut redéfinir (override) une méthode héritée pour changer son comportement.
Attribute #[Override] (PHP 8.3+)
<?php
declare(strict_types=1);
class Forme {
public function __construct(
protected string $couleur
) {}
public function afficher(): void {
echo "Je suis une forme {$this->couleur}.\n";
}
public function calculerAire(): float {
return 0.0;
}
}
class Rectangle extends Forme {
public function __construct(
string $couleur,
private float $largeur,
private float $hauteur
) {
parent::__construct($couleur);
}
#[Override] // PHP 8.3+ : indique qu'on redéfinit une méthode parente
public function afficher(): void {
parent::afficher(); // Appel de la méthode parente
echo "C'est un rectangle de {$this->largeur}x{$this->hauteur}.\n";
}
#[Override]
public function calculerAire(): float {
return $this->largeur * $this->hauteur;
}
}
class Cercle extends Forme {
public function __construct(
string $couleur,
private float $rayon
) {
parent::__construct($couleur);
}
#[Override]
public function afficher(): void {
parent::afficher();
echo "C'est un cercle de rayon {$this->rayon}.\n";
}
#[Override]
public function calculerAire(): float {
return pi() * $this->rayon ** 2;
}
}
$rectangle = new Rectangle("rouge", 5, 3);
$cercle = new Cercle("bleu", 4);
$rectangle->afficher();
echo "Aire : {$rectangle->calculerAire()} unités²\n\n";
$cercle->afficher();
echo "Aire : " . round($cercle->calculerAire(), 2) . " unités²\n";
?>
Sortie :
Je suis une forme rouge.
C'est un rectangle de 5x3.
Aire : 15 unités²
Je suis une forme bleu.
C'est un cercle de rayon 4.
Aire : 50.27 unités²
6.5- Les Niveaux de Visibilité et l’Héritage
| Visibilité | Dans la classe | Dans les enfants | Hors de la classe |
|---|---|---|---|
public |
✅ Oui | ✅ Oui | ✅ Oui |
protected |
✅ Oui | ✅ Oui | ❌ Non |
private |
✅ Oui | ❌ Non | ❌ Non |
<?php
declare(strict_types=1);
class Parent {
public string $public = "Public";
protected string $protected = "Protected";
private string $private = "Private";
public function tester(): void {
echo $this->public; // ✅ OK
echo $this->protected; // ✅ OK
echo $this->private; // ✅ OK
}
}
class Enfant extends Parent {
public function tester(): void {
echo $this->public; // ✅ OK
echo $this->protected; // ✅ OK
// echo $this->private; // ❌ ERREUR : Cannot access private property
}
}
$enfant = new Enfant();
echo $enfant->public; // ✅ OK
// echo $enfant->protected; // ❌ ERREUR
// echo $enfant->private; // ❌ ERREUR
?>
Prêt à passer à la suite ?
Vous avez terminé cette leçon sur Programmation Orientée Objet. Continuez votre apprentissage avec la prochaine leçon ou explorez d'autres formations.