Menu

Surcharge de méthodes en Java : même nom, paramètres différents

Comment la surcharge de méthodes en Java permet à plusieurs méthodes de partager un nom tout en prenant des paramètres différents, comment le compilateur choisit une surcharge et quels pièges d'ambiguïté éviter.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

Un nom, plusieurs versions

Sur la page précédente, vous avez vu comment les paramètres d'une méthode définissent ce qu'elle accepte. La surcharge de méthodes va plus loin : vous pouvez donner à plusieurs méthodes le même nom, à condition que leurs listes de paramètres diffèrent. Le compilateur les traite comme des méthodes distinctes et choisit la bonne selon les arguments que vous passez.

C'est pour cela que System.out.println affiche sans broncher un int, une String, un boolean ou un double : il n'existe pas un seul println, mais de nombreuses surcharges qui partagent le nom. Vous écrivez l'appel que vous voulez et le compilateur l'associe à la version qui convient.

Les deux méthodes s'appellent square, mais l'une prend un int et l'autre un double. Le littéral 5 est un int, donc la première surcharge s'exécute ; 2.5 est un double, donc la seconde s'exécute.

Ce qui compte comme une surcharge différente

Les surcharges doivent différer par leur liste de paramètres, c'est-à-dire au moins par l'un de ces points :

  • un nombre de paramètres différent,
  • des types de paramètres différents, ou
  • un ordre des types différent.

Chaque appel a une liste de paramètres qui correspond exactement à l'une des trois méthodes join, donc aucune confusion possible.

Le type de retour ne compte pas

Un piège fréquent pour les débutants : tenter de surcharger uniquement sur le type de retour. Le type de retour ne fait pas partie de la signature utilisée par le compilateur, donc ceci ne compile pas :

// NE compile PAS - même nom, mêmes paramètres, seul le type de retour diffère
static int   value() { return 1; }
static double value() { return 1.0; }   // erreur : value() est déjà défini

Le compilateur ne peut pas les distinguer, car à un point d'appel comme value(), rien dans les arguments n'indique laquelle vous voulez. Vous pouvez donner des types de retour différents aux surcharges, mais seulement quand leurs listes de paramètres diffèrent déjà.

Comment Java choisit une surcharge

Lorsque plusieurs surcharges pourraient accepter vos arguments, Java choisit la plus spécifique et préfère une correspondance de type exacte à une conversion par élargissement. Regardez ce qui se passe avec un argument int :

show(7) correspond exactement à int, même si long et double pourraient aussi contenir un 7 après élargissement. Ce n'est que si la surcharge exacte était supprimée que le compilateur élargirait int en long, puis en double. Cette résolution est entièrement décidée à la compilation, selon les types déclarés de vos arguments.

Attention aux appels ambigus

Si aucune surcharge n'est clairement la meilleure correspondance, le compilateur refuse de deviner et signale une erreur. Cela se produit surtout avec null, qui convient à n'importe quel type référence :

static void handle(String s) { }
static void handle(StringBuilder b) { }

handle(null);   // erreur : la référence à handle est ambiguë

Les deux surcharges acceptent null et aucune n'est plus spécifique, donc l'appel ne compile pas. Corrigez-le en rendant le type explicite avec un cast - handle((String) null) - ou en repensant la conception pour que les surcharges n'entrent pas en collision. La même prudence s'impose en mélangeant autoboxing et élargissement ; gardez les ensembles de surcharges assez simples pour que chaque appel ait un gagnant évident.

Surcharge de constructeurs

La surcharge ne se limite pas aux méthodes ordinaires : les constructeurs l'utilisent constamment pour proposer plusieurs façons de construire un objet. Un constructeur sans argument peut déléguer à un constructeur plus complet avec this(...) :

Les deux constructeurs partagent le nom Point mais diffèrent par le nombre de paramètres, exactement comme des méthodes surchargées. Déléguer avec this(...) garde la logique d'initialisation à un seul endroit.

Surcharge ou redéfinition

Ces deux termes se ressemblent mais n'ont aucun lien :

  • Surcharge - même nom, listes de paramètres différentes, dans la même classe. Le compilateur choisit la version à la compilation. Il s'agit de proposer des variantes d'une opération.
  • Redéfinition - une sous-classe redéfinit une méthode héritée avec le même nom et les mêmes paramètres. Java choisit la version à l'exécution selon le type réel de l'objet. Il s'agit de remplacer un comportement (vous la rencontrerez avec l'héritage et le polymorphisme).

Si les listes de paramètres sont identiques, vous faites de la redéfinition (ou vous provoquez une erreur de méthode dupliquée dans la même classe) ; si elles diffèrent, vous faites de la surcharge.

Suite : Varargs

La surcharge vous permet d'écrire join(a, b) et join(a, b, c) comme des méthodes distinctes, mais que faire si vous voulez accepter n'importe quel nombre d'arguments sans déclarer une surcharge pour chaque quantité ? La syntaxe varargs de Java permet à une seule méthode de prendre une liste d'arguments de longueur variable, et c'est le sujet de la page suivante.

Questions fréquentes

Qu'est-ce que la surcharge de méthodes en Java ?

La surcharge de méthodes consiste à définir plusieurs méthodes portant le même nom dans la même classe, chacune avec une liste de paramètres différente (nombre de paramètres, types ou ordre des types différents). Le compilateur décide quelle version appeler en comparant les arguments que vous passez aux paramètres de chaque surcharge. C'est une décision prise à la compilation, pas à l'exécution.

Deux méthodes peuvent-elles différer uniquement par leur type de retour en Java ?

Non. Le type de retour ne fait pas partie de la signature d'une méthode pour la surcharge, donc int total() et double total() dans la même classe provoquent une erreur de compilation. Les surcharges doivent différer par leur liste de paramètres : le nombre, les types ou l'ordre des paramètres. Le type de retour peut différer, mais seulement *en plus d'*une différence de paramètres, jamais à lui seul.

Quelle est la différence entre surcharge et redéfinition en Java ?

La surcharge, ce sont plusieurs méthodes au même nom mais avec des paramètres différents dans la même classe, résolues par le compilateur à la compilation. La redéfinition, c'est une sous-classe qui redéfinit une méthode héritée avec le même nom et les mêmes paramètres, résolue à l'exécution selon le type réel de l'objet. La surcharge sert à proposer des variantes ; la redéfinition sert à remplacer un comportement.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER