Polymorphisme

Introduction

Le polymorphisme est un concept de la programmation orientée objet. C'est la capacité d'un objet d'opter pour le type d'un de ces parents sans changer son comportement.

Il permet à une instance de :

  • Changer de type par un type parent.
  • Être vues et manipulées par les autres classes comme un type parent.
  • Conserver le comportement initial de la classe malgré le changement de type.
  • Faire du faible couplage

Note

La notion de hiérarchie de classe doit être respectée !

Cas d'usage

Considérons les classes suivantes :

package fr.zelmoacademy.sample;

import java.time.LocalDate;
import java.time.Period;

public abstract class Pet {

    protected String name;
    protected Float size;
    protected Float weight;
    protected LocalDate birthDate;

    protected Pet() {
    }

    public abstract void talk();

    public void sleep() {
        System.out.println("...zzz...");
    }

    public final Period getAge(){
        return Period.between(LocalDate.now(), birthDate);
    }
}
package fr.zelmoacademy.sample;

public class Cat extends Pet {

    public Cat() {
    }

    @Override
    public void talk() {
        System.out.println("Meow");
    }

    @Override
    public void sleep() {
        System.out.println("Purrr");
    }

    public void huntMice() {
        // ...
    }
}
package fr.zelmoacademy.sample;

public class Dog extends Pet {

    public Dog() {
    }

    @Override
    public void talk() {
        System.out.println("Woof");
    }

    @Override
    public void sleep() {
        super.sleep();                  // Combine l'appel de la classe parent  
        System.out.println("Zzz");      // ET l'appel de la classe enfant.
    }                                   //> Sortie Console:
                                        // ...zzz...
                                        // Zzz
    public void sniff() {
        // ...
    }
}

Mise en œuvre

Déclaration classique :

Cat tom = new Cat();
// tom est de type 'Cat'.
// Toutes les méthodes de la classe 'Cat' sont accessibles.

Dog spike = new Dog();
// spike est de type 'Dog'.
// Toutes les méthodes de la classe 'Dog' sont accessibles.
// Variante en Java 10 avec l'inférence de type:
var tom = new Cat();
var spike = new Dog();

Déclaration polymorphique :

Pet tom = new Cat();
// tom est de type 'Cat'.
// Uniquement les méthodes de la classe 'Pet' sont accessibles.

Pet spike = new Dog();
// tom est de type 'Dog'.
// Uniquement les méthodes de la classe 'Pet' sont accessibles.

Faible couplage :

// Cette méthode peut prendre en paramètre des objets de type 'Pet' ou enfant de 'Pet'.
// C'est à dire 'Cat' ou 'Dog'
public void ownerAskPet(Pet anyPet){
    anyPet.talk();
}

Cette méthode veut pouvoir demander à un animal de compagnie de parler, mais quel que soit l'animal en question. De plus, la réponse de l'animal se doit d'être spécifique au type réel.

Cat tom = new Cat();
ownerAskPet(tom);        // Sortie console: 'Meow'

Dog spike = new Dog();
ownerAskPet(spike);      // Sortie console: 'Woof'

// Variante Java 10
var sylvestre = new Cat();
ownerAskPet(sylvestre); // Sortie console: 'Meow'

Transtypage

Le polymorphisme permet de naturellement type une classe dans sa hiérarchie montante. Le transtypage permet de forcer le type d'un objet vers un objet. Il faut être prudent lors de son usage car le compilateur Java n'est pas en mesure de vérifier le typage. Si le typage est faux, à l'exécution du programme vous aurez une erreur de type : java.lang.ClassCastException.

Note

En Java le transtypage est aussi connu sous le nom de //cast//.

Pet tom = new Cat();  // tom est en réalité de type 'Cat'.

tom.talk();           // Méthode existante dans la classe 'Pet' OK.

tom.huntMice();
    ^^^^^^^^^^------- // Erreur de compilation:
                      // méthode inexistante dans la classe 'Pet'.

// transtypage:
Cat tomCat = (Cat) tom;
tomCat.huntMice();    // Méthode existante dans la classe 'Cat' OK.

// transtypage:
Dog tomDog = (Dog) tom;
              ^^^----- // Erreur d'exécution: 'java.lang.ClassCastException'
                       // tom n'a pas de lien avec la classe 'Dog'.

Note

Le transtypage est du polymorphisme non naturel ! Soyez très prudent lors de son usage, si possible éviter de l'utiliser abusivement.