La surcharge de méthodes (Method Overloading) est un pilier de la programation orientée objet en C#. Elle permet de définir, au sein d'une même classe, plusieurs méthodes portant le même nom mais possédant des signatures différentes. Cette technique est omniprésente dans le framework .NET, notamment avec la méthode Console.WriteLine(), qui peut traiter indifféremment des chaînes de caractères, des entiers ou des nombres décimaux sans changer de nom.
Le problème des noms de méthodes redondants
Sans la surcharge, nous serions contraints de créer des noms uniques pour chaque variation d'une même fonctionnalité, ce qui alourdirait considérablement le code et sa mémorisasion.
// Exemple d'une conception laborieuse sans surcharge
class CalculateurManuel {
public int SommerDeuxEntiers(int a, int b) {
return a + b;
}
public int SommerTroisEntiers(int a, int b, int c) {
return a + b + c;
}
public double SommerDeuxDoubles(double a, double b) {
return a + b;
}
}
Dans cet exemple, l'utilisateur de la classe doit connaître exactement le nom de la méthode correspondant aux types de données qu'il manipule, ce qui est inefficace.
Les règles de la surcharge
Pour qu'une surcharge soit acceptée par le compilateur C#, elle doit respecter trois critères essentiels :
- Unicité de la classe : Les méthodes doivent être définies dans le même bloc de classe.
- Identité du nom : Elles doivent partaegr exactement le même nom.
- Différenciation des paramètres : La liste des paramètres doit différer soit par le nombre d'arguments, soit par le type des données passées.
Notez que le type de retour seul ne suffit pas à distinguer deux méthodes surchargées.
Implémentation technique de la surcharge
Voici comment restructurer la classe précédente en utilisant la surcharge pour simplifier l'interface de programmation :
using System;
namespace ExempleSurcharge {
class Calculatrice {
// Version pour deux entiers
public int Additionner(int val1, int val2) {
Console.WriteLine("Exécution : addition de 2 entiers.");
return val1 + val2;
}
// Version pour trois entiers
public int Additionner(int val1, int val2, int val3) {
Console.WriteLine("Exécution : addition de 3 entiers.");
return val1 + val2 + val3;
}
// Version pour deux nombres décimaux
public double Additionner(double val1, double val2) {
Console.WriteLine("Exécution : addition de 2 doubles.");
return val1 + val2;
}
}
}
Appel et résolution par le compilateur
Lors de l'exécution, le compilateur analyse les arguments fournis lors de l'appel et sélectionne dynamiquement la définition la plus appropriée. Cela offre une grande flexibilité lors du développement.
class Program {
static void Main(string[] args) {
Calculatrice maCalculatrice = new Calculatrice();
// Appelle la version (int, int)
maCalculatrice.Additionner(10, 20);
// Appelle la version (double, double)
maCalculatrice.Additionner(15.5, 4.5);
// Appelle la version (int, int, int)
maCalculatrice.Additionner(1, 2, 3);
}
}
L'avantage principal réside dans la clarté de l'appel système. Le développeur n'a qu'une seule action logique à retenir ("Additionner") et laisse le langage gérer la complexité liée aux types de données.