⚙️ Développement

Programmation orientée objet : classes, héritage et polymorphisme

📅 10 avril 202618 min de lecture
poojavaphppython
Série : Algorithmique et POO
#2 Programmation orientée objet : classes, héritage et polymorphismevous êtes ici
#3 Tests unitaires, débogage et qualité du code#4 Design patterns essentiels : Singleton, Factory, Observer, MVC

Qu'est-ce que la POO ?

La Programmation Orientée Objet modélise le monde réel en objets qui possèdent des données (attributs) et des comportements (méthodes). Elle repose sur 4 piliers : encapsulation, héritage, polymorphisme, abstraction.

Classes et objets

Une classe est un modèle (plan) qui définit la structure et le comportement. Un objet est une instance concrète d'une classe.

// Classe = le plan
public class Etudiant {
    private String nom;
    private int age;
 
    public Etudiant(String nom, int age) {  // Constructeur
        this.nom = nom;
        this.age = age;
    }
 
    public String getNom() { return nom; }
    public void saluer() {
        System.out.println("Bonjour, je suis " + nom);
    }
}
 
// Objet = une instance
Etudiant alice = new Etudiant("Alice", 22);
alice.saluer();  // "Bonjour, je suis Alice"

Constructeur et cycle de vie

Le constructeur initialise l'objet à sa création. Le destructeur (ou finalizer) libère les ressources à la destruction. En Java/C#, le garbage collector gère la mémoire automatiquement. En C++, le destructeur est explicite.

Encapsulation

L'encapsulation masque l'état interne de l'objet et contrôle l'accès via des méthodes publiques (getters/setters).

ModificateurClassePackageSous-classeExterne
private
défaut (package)
protected
public

Principe : attributs en private, accès via des méthodes public. Cela permet de changer l'implémentation interne sans casser le code qui utilise la classe.

Héritage

L'héritage permet à une classe (enfant/fille) de réutiliser les attributs et méthodes d'une autre (parent/mère). La fille peut ajouter de nouveaux membres ou redéfinir (override) le comportement hérité.

public class Personne {
    protected String nom;
    public void sePresenter() {
        System.out.println("Je suis " + nom);
    }
}
 
public class Enseignant extends Personne {
    private String matiere;
 
    @Override
    public void sePresenter() {
        System.out.println("Je suis " + nom + ", enseignant en " + matiere);
    }
}

Héritage simple vs multiple

Java, C#, PHP : héritage simple uniquement (une seule classe parente). Les interfaces compensent ce manque. C++, Python : héritage multiple autorisé (attention au problème du diamant).

Composition vs héritage

L'héritage modélise une relation "est-un" : un Enseignant est une Personne. La composition modélise une relation "a-un" : une Voiture a un Moteur.

En pratique, préférer la composition à l'héritage : plus flexible, moins de couplage.

Polymorphisme

Le polymorphisme permet à un même appel de méthode de produire des comportements différents selon le type réel de l'objet.

Personne p1 = new Personne();
Personne p2 = new Enseignant();  // Type déclaré = Personne, type réel = Enseignant
 
p1.sePresenter();  // "Je suis Alice"
p2.sePresenter();  // "Je suis Bob, enseignant en Maths" → méthode de Enseignant

Surcharge vs redéfinition

Surcharge (overloading) : même nom de méthode, paramètres différents dans la même classe.

public int calculer(int a, int b) { return a + b; }
public double calculer(double a, double b) { return a + b; }

Redéfinition (overriding) : même signature dans une classe fille, remplace le comportement parent.

Classes abstraites et interfaces

Classe abstraite

Une classe abstraite ne peut pas être instanciée. Elle peut contenir des méthodes abstraites (sans corps) et des méthodes concrètes.

public abstract class Forme {
    abstract double aire();          // À implémenter par les filles
    public void afficher() {         // Méthode concrète
        System.out.println("Aire = " + aire());
    }
}

Interface

Une interface définit un contrat : les méthodes que la classe doit implémenter. Pas d'état (pas d'attributs d'instance). Une classe peut implémenter plusieurs interfaces.

public interface Exportable {
    String toJSON();
    String toCSV();
}
 
public interface Imprimable {
    void imprimer();
}
 
public class Etudiant implements Exportable, Imprimable {
    // Doit implémenter toJSON(), toCSV(), imprimer()
}

Quand utiliser quoi ?

Classe abstraiteInterface
HéritageSimple (une seule)Multiple (plusieurs)
AttributsOuiNon (sauf constantes)
Méthodes concrètesOuiOui (default en Java 8+)
UsageBase commune avec du code partagéContrat de comportement

Principes SOLID

LettrePrincipeEn pratique
SSingle ResponsibilityUne classe = une seule responsabilité
OOpen/ClosedOuvert à l'extension, fermé à la modification
LLiskov SubstitutionUne fille remplace la mère sans casser le code
IInterface SegregationInterfaces spécialisées plutôt qu'une grosse interface
DDependency InversionDépendre des abstractions, pas des implémentations

Points clés pour le concours

  • Encapsulation : attributs private, accès via getters/setters
  • Héritage = "est-un", Composition = "a-un" (préférer la composition)
  • Polymorphisme : un même appel, comportement différent selon le type réel
  • Surcharge = même nom + paramètres différents, Redéfinition = même signature en fille
  • Interface = contrat multi-implémentable, Classe abstraite = base commune avec code partagé
  • Principes SOLID pour un code maintenable