Le polymorphisme est un mécanisme important dans la programmation objet. Il permet de modifier le comportement d’une classe fille par rapport à sa classe mère. Le polymorphisme permet d’utiliser l’héritage comme un mécanisme d’extension en adaptant le comportement des objets.
Le principe du polymorphisme repose en Java sur la redéfinition de méthodes entre la classe mère et ses classes filles. Pour que la redéfinition fonctionne, il faut que la méthode qui redéfinit possède une signature correspondante à celle de la méthode orginale.
Un exemple :
Une classe animal :
public class Animal {
public void crier() {
System.out.println("un cri d'animal");
}
}
Deux classes filles :
public class Chat extends Animal {
@Override
public void crier() {
System.out.println("Miaou !");
}
}
public class Chien extends Animal {
@Override
public void crier() {
System.out.println("Whouaf whouaf !");
}
}
Chaque classe fille change le comportement de la méthode crier. Cela signifie qu’un objet de type Chien pour lequel on invoque le méthode crier ne fournira pas le même comportement qu’un objet de type Chat. Et cela, quel que soit le type de la variable qui référence ces objets.
Le comportement :
Animal animal = new Animal();
animal.crier(); // affiche "un cri d'animal"
Chat chat = new Chat();
chat.crier(); // affiche "Miaou !"
Chien chien = new Chien();
chien.crier(); // affiche "Whouaf whouaf !"
animal = chat;
animal.crier(); // affiche "Miaou !"
animal = chien;
animal.crier(); // affiche "Whouaf whouaf !"
Une méthode qui redéfinit, peut avoir une portée différente si et seulement si, celle-ci est plus permissive que celle de la méthode d’origine. Il est donc possible d’augmenter la portée de la méthode mais jamais de la réduire :
- Une méthode de portée package peut être redéfinie avec la portée package mais aussi protected ou public.
- Une méthode de portée protected peut être redéfinie avec la portée protected ou public.
- Une méthode de portée public ne peut être redéfinie qu’avec la portée public.
Le changement de portée dans la redéfinition sert la plupart du temps à placer une implémentation dans la classe parente mais à laisser les classes filles qui le désirent offrir publiquement l’accès à cette méthode.
Les méthodes de portée private ne supportent pas le polymorphisme. En effet, une méthode de portée private n’est accessible uniquement que par la classe qui la déclare. Donc si une classe mère et une classe fille définissent une méthode private avec la même signature, le compilateur les traitera comme deux méthodes différentes.
Une méthode peut avoir le mot-clé final dans sa signature. Cela signifie que cette méthode ne peut plus être redéfinie par les classes qui en hériteront. Tenter de redéfinir une méthode déclarée final conduit à une erreur de compilation. L’utilisation du mot-clé final pour une méthode est réservée à des cas très spécifiques (et très rares). Par exemple si on souhaite garantir qu’une méthode aura toujours le même comportement même dans les classes qui en héritent.
Les annotations sont des types spéciaux en Java qui commence par @. Les annotations servent à ajouter une information sur une classe, un attribut, une méthode, un paramètre ou une variable. Une annotation apporte une information au moment de la compilation, du chargement de la classe dans la JVM ou lors de l’exécution du code. Le langage Java proprement dit utilise relativement peu les annotations. On trouve cependant l’annotation @Override qui est très utile pour le polymorphisme. Cette annotation s’ajoute au début de la signature d’une méthode pour préciser que cette méthode est une redéfinition d’une méthode héritée. Cela permet au compilateur de vérifier que la signature de la méthode correspond bien à une méthode d’une classe parente. Dans le cas contraire, la compilation échoue.
Le mot-clé instanceof vérifie si un objet est une instance d’une classe spécifique ou une interface.
public class MaClasse {
public static void main(String[] args) {
MaClasse obj = new MaClasse();
System.out.println(obj instanceof MaClasse);
}
}
Le code précédent renvoie True