CodeGym /Cours /JAVA 25 SELF /Utiliser le polymorphisme en pratique

Utiliser le polymorphisme en pratique

JAVA 25 SELF
Niveau 18 , Leçon 3
Disponible

1. Le polymorphisme dans les collections: pourquoi en a-t-on besoin?

Commençons par une question : « À quoi sert le polymorphisme dans les programmes réels? »

Imaginez un zoo. Vous avez une classe de base Animal, ainsi qu’une flopée de sous-classes : Dog, Cat, Cow, Parrot et même Platypus (ornithorynque, pour les amateurs d’exotisme). Chacune sait émettre un son (makeSound()), mais le fait à sa manière.

Au lieu de créer des tableaux séparés pour chaque animal, vous déclarez un tableau ou une liste de type Animal et vous y placez n’importe lequel d’entre eux :

Animal[] animals = {
    new Dog(),
    new Cat(),
    new Cow(),
    new Parrot()
};

Vous pouvez maintenant parcourir ce tableau et appeler makeSound() pour chacun :

for (Animal animal : animals) {
    animal.makeSound();
}

Magie! Chaque objet sait lui-même quel son émettre, et vous n’avez pas besoin d’écrire une foule de if ou de switch.

Exemple par analogie

C’est comme si vous donniez la commande « Parle! » à un groupe d’animaux, et que chacun décidait quoi faire : le chien aboie, le chat miaule et la vache — beugle. Vous ne précisez pas qui est qui — vous appelez simplement la même méthode.

2. Exemple pratique: hiérarchie d’employés

Faisons un exemple plus proche de la vie (et du futur travail en IT). Imaginons que nous ayons une entreprise avec différents employés : des managers, des développeurs, des testeurs. Chacun a une méthode work(), mais elle s’exécute différemment.

Déclaration de la classe de base

public class Employee {
    public void work() {
        System.out.println("L'employé travaille...");
    }
}

Sous-classes

public class Manager extends Employee {
    @Override
    public void work() {
        System.out.println("Le manager tient une réunion.");
    }
}

public class Developer extends Employee {
    @Override
    public void work() {
        System.out.println("Le développeur écrit du code.");
    }
}

public class Tester extends Employee {
    @Override
    public void work() {
        System.out.println("Le testeur cherche des bugs.");
    }
}

Utilisation d’un tableau/liste du type de base

public class CompanyDemo {
    public static void main(String[] args) {
        Employee[] team = {
            new Manager(),
            new Developer(),
            new Tester(),
            new Developer()
        };

        for (Employee e : team) {
            e.work(); // La "bonne" version de la méthode sera appelée pour chaque objet
        }
    }
}

Résultat de l’exécution:

Le manager tient une réunion.
Le développeur écrit du code.
Le testeur cherche des bugs.
Le développeur écrit du code.

Quels sont les avantages?

  • Vous n’écrivez pas une tonne de vérifications du type « Si c’est un Developer — fais ceci/cela ».
  • Ajouter un nouvel employé (par exemple, Designer) — il suffit de créer une nouvelle classe et de l’ajouter au tableau.
  • Le code qui utilise le tableau d’employés ne change pas du tout!

3. Avantages du polymorphisme: flexibilité et extensibilité

Imaginons qu’un nouveau type d’employé apparaisse dans votre entreprise — un Designer. Tout ce que vous avez à faire, c’est créer une nouvelle classe :

public class Designer extends Employee {
    @Override
    public void work() {
        System.out.println("Le designer réalise des maquettes.");
    }
}

On peut maintenant ajouter le designer à l’équipe :

Employee[] team = {
    new Manager(),
    new Developer(),
    new Tester(),
    new Designer()
};

Et voilà! Le programme commence immédiatement à fonctionner correctement avec ce nouveau type d’employé, sans changer une ligne de code dans la partie qui parcourt le tableau et appelle work().

C’est cela, l’extensibilité : votre code s’adapte facilement à de nouveaux types d’objets.

4. Limites du polymorphisme: l’envers de la médaille

Hélas, toute magie a ses limites (et un prix, comme dans n’importe quel RPG).

Seules les méthodes de la classe de base sont disponibles

Quand vous travaillez avec une variable de type Employee, vous ne pouvez appeler que les méthodes déclarées dans la classe Employee. Si la classe Developer possède une méthode spécifique writeCode(), vous ne pourrez pas l’appeler directement :

Employee e = new Developer();
// e.writeCode(); // Erreur de compilation: aucune méthode de ce type dans Employee!

Si vous tenez absolument à appeler une méthode spécifique, il faudra faire un cast. Mais c’est un dernier recours. Si vous faites souvent des casts, il vaut sans doute la peine de revoir la conception des classes — la classe de base ou l’interface doit contenir la méthode nécessaire.

if (e instanceof Developer) {
    Developer dev = (Developer) e;
    dev.writeCode();
}

Mais dans ce cas, vous perdez l’universalité et l’élégance qui faisaient tout l’intérêt de l’approche. Essayez donc de concevoir la classe de base de sorte qu’elle ne contienne que les méthodes réellement nécessaires à tous les sous-classes.

5. Pratique: implémenter une hiérarchie d’employés

Allions l’utile à l’agréable : écrivons une petite application où il existe plusieurs types d’employés et utilisons le polymorphisme pour les traiter.

Étape 1: classe de base et sous-classes

// Employee.java
public class Employee {
    public void work() {
        System.out.println("L'employé travaille...");
    }
}

// Manager.java
public class Manager extends Employee {
    @Override
    public void work() {
        System.out.println("Le manager tient une réunion.");
    }
}

// Developer.java
public class Developer extends Employee {
    @Override
    public void work() {
        System.out.println("Le développeur écrit du code.");
    }
}

// Tester.java
public class Tester extends Employee {
    @Override
    public void work() {
        System.out.println("Le testeur cherche des bugs.");
    }
}

Étape 2: classe principale

// CompanyDemo.java
public class CompanyDemo {
    public static void main(String[] args) {
        Employee[] team = {
            new Manager(),
            new Developer(),
            new Tester(),
            new Developer()
        };

        for (Employee e : team) {
            e.work();
        }
    }
}

Étape 3: ajout d’extensibilité

Supposons que, dans un mois, un nouveau collaborateur arrive dans l’entreprise — un designer. Tout ce qu’il faut :

public class Designer extends Employee {
    @Override
    public void work() {
        System.out.println("Le designer réalise des maquettes.");
    }
}

Voilà, on peut maintenant ajouter le designer à l’équipe :

Employee[] team = {
    new Manager(),
    new Developer(),
    new Tester(),
    new Designer()
};

Bilan

Tout le code principal (CompanyDemo) est resté inchangé! C’est la force du polymorphisme.

6. Erreurs courantes lors de l’utilisation du polymorphisme

Erreur n° 1: Attendre l’accès à des méthodes spécifiques via une référence du type de base.
Très souvent, les débutants essaient d’appeler des méthodes spécifiques d’une sous-classe via une variable du type de la super-classe. Par exemple :

Employee e = new Developer();
// e.writeCode(); // Erreur! Cette méthode n'est pas définie dans Employee.

Pour appeler une méthode spécifique, il faut faire un cast, mais on perd alors l’universalité.

Erreur n° 2: Ne pas utiliser l’annotation @Override.
Si vous oubliez l’annotation, vous pouvez par erreur écrire une nouvelle méthode au lieu d’un override (par exemple, en vous trompant dans le nom). Le polymorphisme ne fonctionnera alors pas, et c’est la version de la super-classe qui sera appelée.

Erreur n° 3: Absence d’une interface commune.
Si la classe de base ne contient pas la méthode requise, le polymorphisme est impossible. Par exemple, si Employee n’a pas de méthode work(), alors la boucle sur le tableau d’employés ne pourra pas appeler cette méthode pour tous.

Erreur n° 4: Violation du principe d’ouverture/fermeture.
Si, pour ajouter un nouveau type d’employé, il faut modifier le code qui parcourt le tableau/la liste, c’est que vous n’utilisez pas correctement le polymorphisme.

Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION