L'outrepassement (overriding) des méthodes représente l'autre mode d'implémentation du polymorphisme dans le langage Java, permettant la redéfinition du comportement d'une ou plusieurs méthodes d'une superclasse, à partir d'une classe étendue.
Une méthode d'instance (public, protected ou par défaut) déclarée dans une superclasse peut être outrepassée (override) dans une autre classe :
Une méthode statique déclarée dans une superclasse ou une interface peut être cachée (hide) par une autre méthode statique :
Malgré la différence précitée entre les méthodes d'instance et de classe, les règles d'outrepassement sont exactement les mêmes dans les deux cas.
Une erreur de compilation se produit si une méthode d'instance tente d'outrepasser une méthode statique et inversement.
class SuperClasse { static void methodeClasse(){ ... } } class ClasseDerivee extends SuperClasse { // erreur de compilation public void methodeClasse(){ ... } }
L'outrepassement (parfois remplacement) est autorisé si les deux méthodes possèdent un nom, une liste de paramètres et un type de retour identiques, mais l'une (méthode d'origine) doit être localisée dans une superclasse et l'autre (méthode outrepassée) dans une classe dérivée.
class UneClasse { modificateur type uneMethode(type un_parametre) [throws ClasseException] { ... } } class UneClasseEtendue extends UneClasse { modificateur type uneMethode(type un_parametre) [throws ClasseException] { ... } }
Les identificateurs des paramètres peuvent être différents dans les deux méthodes sans avoir aucune incidence sur le bon fonctionnement du programme.
Par contre, les paramètres doivent posséder exactement les mêmes types et le même ordre que dans la méthode à outrepasser.
Le modificateur d'accès de la méthode outrepassée ne doit pas être plus restrictif que celui de la méthode de la superclasse.
Méthode d'origine | Méthode outrepassée |
---|---|
par défaut | par défaut, protected ou public |
protected | protected ou public |
public | public |
Sémantiquement, une méthode de superclasse privée entraîne une impossiblité d'appliquer une surcharge ou un outrepassement à partir d'une classe étendue puisqu'elle ne peut être héritée par une sous-classe.
Cependant techniquement, une sous-classe peut parfaitement posséder une méthode d'une signature identique à une autre déclarée avec le modificateur d'accès private dans une superclasse sans engendrer d'erreur. Mais dans ce cas, aucune relation n'existe entre les deux méthodes.
En outre, une méthode de superclasse ne peut être outrepassée pour devenir privée dans une classe étendue.
De même, une méthode finale ne peut être outrepassée car elle ne peut être modifiée.
Par ailleurs, s'il existe une clause throws dans la déclaration de la méthode d'origine, celle outrepassée doit obligatoirement spécifier les mêmes types d'exceptions afin d'éviter tout conflit conduisant fatalement à une erreur de compilation.
Parfois, il peut être utile de pouvoir appeler la méthode de la superclasse, outrepassée dans la classe en cours. Cela est possible en utilisant le mot-clé super faisant référence à la superclasse.
class SuperClasse { public void uneMethode(String un_parametre){ System.out.println("SuperClasse : " + un_parametre); } } class UneClasse extends SuperClasse { public void uneMethode(String un_parametre){ System.out.println("UneClasse : " + un_parametre); } public void uneMethodeDeSuperClasse(String un_parametre){ super.uneMethode(un_parametre); } } class Prog { public static void main(String[] args){ String l_argument = ""; if(args.length > 0) { for(int i = 0; i < args.length; i++){ l_argument += args[i] + " "; } } UneClasse ref_obj = new UneClasse(); ref_obj.uneMethode(l_argument); ref_obj.uneMethodeDeSuperClasse(l_argument); // affiche : // UneClasse : argument... // SuperClasse : argument... } }
Le mot-clé super ne peut être utilisé que pour appeler une méthode dans la classe immédiatement supérieure. Par exemple, si une troisième classe héritait de la classe UneClasse, le mot-clé super ne pourrait être utilisé deux fois (super.super.methode()) pour appeler directement la méthode de la classe SuperClasse.
class UneTroisiemeClasse extends UneClasse { public void uneMethode(String un_parametre){ System.out.println("UneTroisiemeClasse : " + un_parametre); } public void uneMethodeDeSuperSuperClasse(String un_parametre){ // formulation incorrecte super.super.uneMethode(un_parametre); // formulation correcte super.uneMethodeDeSuperClasse(un_parametre); } }