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