Le polymorphisme est un principe qui permet à une variable objet de prendre différentes “formes” au cours de l’exécution, c.a.d référencer des instances de classes différentes, MAIS sous contraintes :
Sinon, il y aura une erreur de compilation
class A{}, class B extends A{}, class C extends A{}, class D extends B{},
A a = new A(); // OK
A a = new B(); // OK
A a = new C(); // OK
B b = new A(); // ERR
B b = new B(); // OK
B b = new C(); // ERR
C c = new D(); // ERR
C c = new B(); // ERR
C c = new C(); // OK
D d = new D();
a = d; // OK car D hérite de B qui hérite de A
b = d; // OK car D hérité de B
c = d; // ERR (ce qui est a droite n'hérite pas de ce qui est à gauche)
Généralement, la polymorphie n’a pas d’intérêt propre et ne trouve son utilité qu’en conjonction avec la redéfinition.
Imaginons un système de gestion de formes géométriques. Nous allons créer une classe de base Forme et quelques sous-classes comme Cercle et Rectangle. Chaque forme aura une méthode pour calculer sa surface, mais cette méthode sera implémentée différemment pour chaque type de forme.
// Classe de base
abstract class Forme {
abstract double calculerSurface();
void afficherSurface() {
System.out.println("La surface est : " + calculerSurface());
}
}
// Sous-classe Cercle
class Cercle extends Forme {
private double rayon;
public Cercle(double rayon) {
this.rayon = rayon;
}
@Override
double calculerSurface() {
return Math.PI * rayon * rayon;
}
}
// Sous-classe Rectangle
class Rectangle extends Forme {
private double longueur;
private double largeur;
public Rectangle(double longueur, double largeur) {
this.longueur = longueur;
this.largeur = largeur;
}
@Override
double calculerSurface() {
return longueur * largeur;
}
}
// Classe principale pour tester
public class TestFormes {
public static void main(String[] args) {
// Utilisation du polymorphisme
Forme[] formes = new Forme[3];
formes[0] = new Cercle(5);
formes[1] = new Rectangle(4, 6);
formes[2] = new Cercle(3);
// Calcul et affichage des surfaces
for (Forme forme : formes) {
forme.afficherSurface();
}
}
}
Dans cet exemple :
Forme avec une méthode abstraite calculerSurface() et une méthode concrète afficherSurface().Cercle et Rectangle héritent de Forme et redéfinissent la méthode calculerSurface() selon leurs propres caractéristiques.main(), nous utilisons le polymorphisme en créant un tableau de Forme qui peut contenir des instances de Cercle et de Rectangle.afficherSurface() sur chaque élément.L'utilité du polymorphisme ici est multiple :
Forme, sans nous soucier de leur type spécifique.Forme et implémente calculerSurface().afficherSurface() est définie une seule fois dans la classe de base et peut être utilisée par toutes les sous-classes.Forme