CodeGym /Cours /C# SELF /Surcharge de méthodes (Method Overloading)

Surcharge de méthodes (Method Overloading)

C# SELF
Niveau 21, Leçon 1
Disponible

1. Introduction

Dans la vraie vie, plein d'actions ressemblent à des couteaux suisses multifonctions : une même commande peut bosser avec différents outils. Imagine un distributeur de billets : si tu insères une carte, il te demande ton code PIN ; si tu tapes un numéro de téléphone, il attend un code de confirmation par SMS. L'action c'est "vérifier l'utilisateur", mais la façon de faire change.

En prog, on tombe souvent sur la même situation : tu veux faire une opération, mais les données peuvent être de types différents ou avec un nombre de paramètres variable. Par exemple, ta méthode doit afficher un message de bienvenue pour une personne ou un animal, ou additionner deux, trois, voire dix entiers.

Bien sûr, tu pourrais nommer tes méthodes différemment : SumTwo, SumThree, SumArray. Mais les devs sont flemmards (on dit que la flemme, c'est le moteur du progrès !). Et puis, ton code serait moins lisible.

Surcharge de méthode

La surcharge de méthodes — c'est une façon de "forcer" une même méthode à bosser avec différents ensembles de paramètres, sans changer son nom. C'est une forme de polymorphisme, mais pas liée à l'héritage.

La surcharge de méthode, c'est la possibilité de créer dans une même classe (ou struct) plusieurs méthodes avec le même nom, mais avec des listes de paramètres différentes (par type, nombre et/ou ordre).

Signature de la méthode

La signature d'une méthode en C# — c'est son nom plus le(s) type(s) et l'ordre des paramètres. Le type de retour de la méthode ne fait PAS partie de la signature ! Ça cause souvent des bugs surprises (je t'en parle juste après).

2. Surcharge en action : exemples simples

On va créer une classe Greeter qui va saluer les utilisateurs de différentes façons : juste par le nom, par nom et âge, ou sans paramètre du tout.


public class Greeter
{
    // Salutation sans paramètres
    public void Greet()
    {
        Console.WriteLine("Salut, le monde !");
    }

    // Salutation avec le nom
    public void Greet(string name)
    {
        Console.WriteLine($"Salut, {name} !");
    }

    // Salutation avec nom et âge
    public void Greet(string name, int age)
    {
        Console.WriteLine($"Salut, {name} ! T'as déjà {age} ans ? Pas mal !");
    }
}

Maintenant tu peux appeler n'importe laquelle de ces méthodes, et le compilateur C# va choisir la bonne version — selon le nombre et le type des paramètres que tu passes.

var greeter = new Greeter();
greeter.Greet();                // Salut, le monde !
greeter.Greet("Ania");          // Salut, Ania !
greeter.Greet("Piotr", 23);     // Salut, Piotr ! T'as déjà 23 ans ? Pas mal !

3. Différence par type et nombre de paramètres

La surcharge marche si les méthodes diffèrent par :

  • le nombre de paramètres,
  • le type d'au moins un paramètre,
  • l'ordre des types de paramètres (mais là, fais gaffe).

Essayons d'ajouter une surcharge qui prend juste l'âge :


public void Greet(int age)
{
    Console.WriteLine($"Cet âge — c'est stylé ! ({age} ans)");
}

Maintenant, les appels :

greeter.Greet(10);          // Cet âge — c'est stylé ! (10 ans)

À retenir : si les méthodes ne diffèrent que par le type de retour, tu ne peux pas les surcharger. Par exemple, ce code va planter :


// Erreur de compilation !
public int Foo(string s) { ... }
public double Foo(string s) { ... }
Impossible de surcharger juste par le type de retour !

Le compilateur va râler : "La méthode Foo(string) existe déjà, fais plus compliqué !"

4. Surcharge et la bibliothèque standard C#

La surcharge, c'est pas juste notre Greet inventé. Ouvre la doc .NET pour Console.WriteLine :

Signature But
WriteLine()
Affiche une ligne vide
WriteLine(string)
Affiche une chaîne
WriteLine(int)
Affiche un entier
WriteLine(double)
Affiche un nombre à virgule
WriteLine(string, object)
Formate une chaîne avec un argument
WriteLine(string, params object[])
Formate avec plusieurs arguments

Tout ça, c'est des surcharges de la même méthode — WriteLine. Maintenant tu piges pourquoi tu peux toujours faire :

Console.WriteLine("Juste une chaîne");
Console.WriteLine(123);
Console.WriteLine(2.5);
Console.WriteLine("Somme : {0}", 42);

Et le compilateur comprend toujours ton appel !

5. Comment le compilateur choisit quelle surcharge appeler ?

C'est carré : il regarde les types et le nombre d'arguments que tu passes. Un petit tableau pour illustrer :

Appel Quelle version sera appelée ?
greeter.Greet()
void Greet()
greeter.Greet(75)
void Greet(int)

Et en cas d'ambiguïté ?

Parfois, ça part en cacahuète. Exemple de surcharge ambiguë — le compilateur ne saura pas quelle version choisir


public void Print(int a, double b) { ... }
public void Print(double a, int b) { ... }

printer.Print(5, 10); 
// Erreur : ambiguïté — quelle Print appeler ? (les deux pourraient marcher)

Le compilateur va sortir une erreur d'ambiguïté. Dans ces cas-là, évite les surcharges avec le même nombre de paramètres et des types proches, ça peut embrouiller le compilateur.

6. params — nombre variable de paramètres

Imaginons que tu veux une méthode qui prend un nombre indéfini de nombres. Le mot-clé params est là pour toi.


public void SumAll(params int[] numbers)
{
    int sum = 0;
    foreach (int n in numbers)
        sum += n;
    Console.WriteLine($"Somme : {sum}");
}
Méthode avec nombre variable de paramètres ( params)

Maintenant tu peux appeler :

SumAll(1, 2, 3);           // Somme : 6
SumAll(10, 20);            // Somme : 30
SumAll();                  // Somme : 0

Tu peux combiner params avec la surcharge, mais fais gaffe à ne pas créer des surcharges qui rendent le choix du compilateur ambigu.

7. Surcharge et modificateurs de paramètres (ref, out, in)

C# distingue les méthodes par les modificateurs de paramètres (donc la signature void Foo(int a) est différente de void Foo(ref int a), et les deux peuvent exister dans la même classe) :

public void SetValue(int a)
{
    a = 42;
}

public void SetValue(ref int a)
{
    a = 100;
}
Surcharge par le modificateur ref

Un appel sans ref va sur la première version, avec ref — sur la seconde :

int n = 5;
SetValue(n);     // n reste 5 (valeur copiée)
SetValue(ref n); // n devient 100

8. Schéma : c'est quoi la surcharge


      +----------+
      |  MyClass |
      +----------+
           |
           |            (extrait de méthodes)
    +-----------------------+
    |   void Foo()          |
    |   void Foo(int a)     |
    |   void Foo(string s)  |
    |   void Foo(int a, int b) |
    +-----------------------+
Schéma de surcharge de méthodes dans une classe

Et si on imagine ça en code :

// On appelle les versions surchargées de Foo():
var mc = new MyClass();
mc.Foo();              // void Foo()
mc.Foo(5);             // void Foo(int)
mc.Foo("Hello");       // void Foo(string)
mc.Foo(2, 3);          // void Foo(int, int)

9. Exemple : surcharge de méthodes dans notre appli

On continue à faire évoluer notre appli d'apprentissage, en ajoutant la surcharge de méthode dans la hiérarchie des animaux.


public class Animal
{
    public string Name { get; set; }

    // Méthode pour faire un son
    public virtual void MakeSound()
    {
        Console.WriteLine("Un son chelou...");
    }

    // Méthode surchargée : son avec volume
    public void MakeSound(int volume)
    {
        Console.WriteLine($"L'animal fait un son de {volume} dB.");
    }
}

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Ouaf !");
    }

    // Méthode surchargée : aboiement avec volume
    public void MakeSound(int volume)
    {
        Console.WriteLine($"Ouaf ! (volume : {volume} dB)");
    }
}

Teste ces appels :

Dog rex = new Dog();
rex.MakeSound();           // Ouaf !
rex.MakeSound(75);         // Ouaf ! (volume : 75 dB)

À noter : dans la classe héritée (Dog), on a surchargé la méthode MakeSound(int volume), donc maintenant elle existe en deux versions : avec ou sans paramètre.

10. Erreurs classiques avec la surcharge de méthodes

Erreur n°1 : essayer de surcharger juste par le type de retour.
C'est impossible — le type de retour ne fait pas partie de la signature. La surcharge doit différer par le nombre ou le type des paramètres d'entrée, pas par void ou int.

Erreur n°2 : surcharges ambiguës qui embrouillent le compilateur.
Les surcharges avec le même nombre de paramètres et des types proches (genre int et double) peuvent paumer le compilateur. Exemple : Print(int a, double b) et Print(double a, int b) — l'appel Print(1, 1) va donner une erreur d'ambiguïté.

Erreur n°3 : conflit params avec d'autres surcharges.
Une méthode avec params peut attraper un appel destiné à une autre surcharge. Si les types collent, le compilateur peut choisir la mauvaise méthode.

Erreur n°4 : oublier que ref et out font partie de la signature.
Les méthodes Do(ref int x) et Do(out int x) sont considérées comme des surcharges différentes. Si tu oublies ça, tu peux vite te planter et appeler la mauvaise version.

2
Mission
C# SELF, niveau 21, leçon 1
Bloqué
Création de méthodes surchargées pour calculer l'aire des figures
Création de méthodes surchargées pour calculer l'aire des figures
2
Mission
C# SELF, niveau 21, leçon 1
Bloqué
Méthode pour l'affichage formaté des données
Méthode pour l'affichage formaté des données
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION