Savoir quand utiliser les mots clés override et new (Guide de programmation C#)Knowing When to Use Override and New Keywords (C# Programming Guide)

En C#, une méthode dans une classe dérivée peut avoir le même nom qu’une méthode dans la classe de base.In C#, a method in a derived class can have the same name as a method in the base class. Vous pouvez spécifier le mode d’interaction des méthodes avec les mots clés new et override.You can specify how the methods interact by using the new and override keywords. Le modificateur overrideétend la méthode virtual de la classe de base, tandis que le modificateur newmasque une méthode de classe de base accessible.The override modifier extends the base class virtual method, and the new modifier hides an accessible base class method. La différence est illustrée dans les exemples de cette rubrique.The difference is illustrated in the examples in this topic.

Dans une application console, déclarez les deux classes suivantes, BaseClass et DerivedClass.In a console application, declare the following two classes, BaseClass and DerivedClass. DerivedClass hérite de BaseClass.DerivedClass inherits from BaseClass.

class BaseClass  
{  
    public void Method1()  
    {  
        Console.WriteLine("Base - Method1");  
    }  
}  
  
class DerivedClass : BaseClass  
{  
    public void Method2()  
    {  
        Console.WriteLine("Derived - Method2");  
    }  
}  

Dans la méthode Main, déclarez les variables bc, dc et bcdc.In the Main method, declare variables bc, dc, and bcdc.

  • bc est de type BaseClass et sa valeur est de type BaseClass.bc is of type BaseClass, and its value is of type BaseClass.

  • dc est de type DerivedClass et sa valeur est de type DerivedClass.dc is of type DerivedClass, and its value is of type DerivedClass.

  • bcdc est de type BaseClass et sa valeur est de type DerivedClass.bcdc is of type BaseClass, and its value is of type DerivedClass. Il s’agit de la variable à surveiller.This is the variable to pay attention to.

Comme bc et bcdc ont le type BaseClass, ils ne peuvent accéder directement qu’à Method1, sauf si vous effectuez un cast.Because bc and bcdc have type BaseClass, they can only directly access Method1, unless you use casting. La variable dc peut accéder à Method1 et Method2.Variable dc can access both Method1 and Method2. Ces relations sont illustrées dans le code suivant.These relationships are shown in the following code.

class Program  
{  
    static void Main(string[] args)  
    {  
        BaseClass bc = new BaseClass();  
        DerivedClass dc = new DerivedClass();  
        BaseClass bcdc = new DerivedClass();  
  
        bc.Method1();  
        dc.Method1();  
        dc.Method2();  
        bcdc.Method1();  
    }  
    // Output:  
    // Base - Method1  
    // Base - Method1  
    // Derived - Method2  
    // Base - Method1  
}  

Ensuite, ajoutez la méthode Method2 suivante à BaseClass.Next, add the following Method2 method to BaseClass. La signature de cette méthode correspond à celle de la méthode Method2 dans DerivedClass.The signature of this method matches the signature of the Method2 method in DerivedClass.

public void Method2()  
{  
    Console.WriteLine("Base - Method2");  
}  

Comme BaseClass a maintenant une méthode Method2, une deuxième instruction d’appel peut être ajoutée pour les variables BaseClass``bc et bcdc, comme illustré dans le code suivant.Because BaseClass now has a Method2 method, a second calling statement can be added for BaseClass variables bc and bcdc, as shown in the following code.

bc.Method1();  
bc.Method2();  
dc.Method1();  
dc.Method2();  
bcdc.Method1();  
bcdc.Method2();  

Quand vous générez le projet, vous constatez que l’ajout de la méthode Method2 dans BaseClass génère un avertissement.When you build the project, you see that the addition of the Method2 method in BaseClass causes a warning. L’avertissement indique que la méthode Method2 dans DerivedClass masque la méthode Method2 dans BaseClass.The warning says that the Method2 method in DerivedClass hides the Method2 method in BaseClass. Il est recommandé d’utiliser le mot clé new dans la définition de Method2 si vous avez l’intention de provoquer ce résultat.You are advised to use the new keyword in the Method2 definition if you intend to cause that result. Sinon, vous pouvez renommer l’une des méthodes Method2 pour résoudre l’avertissement, mais ce n’est pas toujours pratique.Alternatively, you could rename one of the Method2 methods to resolve the warning, but that is not always practical.

Avant d’ajouter new, exécutez le programme pour afficher la sortie produite par les instructions d’appel supplémentaires.Before adding new, run the program to see the output produced by the additional calling statements. Les résultats suivants s'affichent.The following results are displayed.

// Output:  
// Base - Method1  
// Base - Method2  
// Base - Method1  
// Derived - Method2  
// Base - Method1  
// Base - Method2  

Le mot clé new conserve les relations qui génèrent cette sortie, mais supprime l’avertissement.The new keyword preserves the relationships that produce that output, but it suppresses the warning. Les variables de type BaseClass continuent d’accéder aux membres de BaseClass et la variable de type DerivedClass continue d’accéder aux membres dans DerivedClass avant de prendre en compte les membres hérités de BaseClass.The variables that have type BaseClass continue to access the members of BaseClass, and the variable that has type DerivedClass continues to access members in DerivedClass first, and then to consider members inherited from BaseClass.

Pour supprimer l’avertissement, ajoutez le modificateur new à la définition de Method2 dans DerivedClass, comme illustré dans le code suivant.To suppress the warning, add the new modifier to the definition of Method2 in DerivedClass, as shown in the following code. Le modificateur peut être ajouté avant ou après public.The modifier can be added before or after public.

public new void Method2()  
{  
    Console.WriteLine("Derived - Method2");  
}  

Réexécutez le programme pour vérifier que la sortie n’a pas changé.Run the program again to verify that the output has not changed. Vérifiez aussi que l’avertissement ne s’affiche plus.Also verify that the warning no longer appears. À l’aide de new, vous déclarez que vous êtes conscient que le membre qu’il modifie masque un membre hérité de la classe de base.By using new, you are asserting that you are aware that the member that it modifies hides a member that is inherited from the base class. Pour plus d’informations sur le masquage de nom par héritage, consultez new, modificateur.For more information about name hiding through inheritance, see new Modifier.

Pour comparer ce comportement aux effets de l’utilisation de override, ajoutez la méthode suivante à DerivedClass.To contrast this behavior to the effects of using override, add the following method to DerivedClass. Le modificateur override peut être ajouté avant ou après public.The override modifier can be added before or after public.

public override void Method1()  
{  
    Console.WriteLine("Derived - Method1");  
}  

Ajoutez le modificateur virtual à la définition de Method1 dans BaseClass.Add the virtual modifier to the definition of Method1 in BaseClass. Le modificateur virtual peut être ajouté avant ou après public.The virtual modifier can be added before or after public.

public virtual void Method1()  
{  
    Console.WriteLine("Base - Method1");  
}  

Réexécutez le projet.Run the project again. Notez en particulier les deux dernières lignes de la sortie suivante.Notice especially the last two lines of the following output.

// Output:  
// Base - Method1  
// Base - Method2  
// Derived - Method1  
// Derived - Method2  
// Derived - Method1  
// Base - Method2  

L’utilisation du modificateur override permet à bcdc d’accéder à la méthode Method1 définie dans DerivedClass.The use of the override modifier enables bcdc to access the Method1 method that is defined in DerivedClass. En règle générale, il s’agit du comportement souhaité dans les hiérarchies d’héritage.Typically, that is the desired behavior in inheritance hierarchies. Vous voulez que les objets dont les valeurs sont créées à partir de la classe dérivée utilisent les méthodes définies dans la classe dérivée.You want objects that have values that are created from the derived class to use the methods that are defined in the derived class. Vous obtenez ce comportement en utilisant override pour étendre la méthode de classe de base.You achieve that behavior by using override to extend the base class method.

Le code suivant contient l’exemple complet.The following code contains the full example.

using System;  
using System.Text;  
  
namespace OverrideAndNew  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            BaseClass bc = new BaseClass();  
            DerivedClass dc = new DerivedClass();  
            BaseClass bcdc = new DerivedClass();  
  
            // The following two calls do what you would expect. They call  
            // the methods that are defined in BaseClass.  
            bc.Method1();  
            bc.Method2();  
            // Output:  
            // Base - Method1  
            // Base - Method2  
  
            // The following two calls do what you would expect. They call  
            // the methods that are defined in DerivedClass.  
            dc.Method1();  
            dc.Method2();  
            // Output:  
            // Derived - Method1  
            // Derived - Method2  
  
            // The following two calls produce different results, depending
            // on whether override (Method1) or new (Method2) is used.  
            bcdc.Method1();  
            bcdc.Method2();  
            // Output:  
            // Derived - Method1  
            // Base - Method2  
        }  
    }  
  
    class BaseClass  
    {  
        public virtual void Method1()  
        {  
            Console.WriteLine("Base - Method1");  
        }  
  
        public virtual void Method2()  
        {  
            Console.WriteLine("Base - Method2");  
        }  
    }  
  
    class DerivedClass : BaseClass  
    {  
        public override void Method1()  
        {  
            Console.WriteLine("Derived - Method1");  
        }  
  
        public new void Method2()  
        {  
            Console.WriteLine("Derived - Method2");  
        }  
    }  
}  

L’exemple suivant illustre un comportement similaire dans un autre contexte.The following example illustrates similar behavior in a different context. L’exemple définit trois classes : une classe de base nommée Car et deux de ses classes dérivées, ConvertibleCar et Minivan.The example defines three classes: a base class named Car and two classes that are derived from it, ConvertibleCar and Minivan. La classe de base contient une méthode DescribeCar.The base class contains a DescribeCar method. La méthode affiche une description de base d’une voiture et appelle ensuite ShowDetails pour fournir des informations supplémentaires.The method displays a basic description of a car, and then calls ShowDetails to provide additional information. Chacune des trois classes définit une méthode ShowDetails.Each of the three classes defines a ShowDetails method. Le modificateur new est utilisé pour définir ShowDetails dans la classe ConvertibleCar.The new modifier is used to define ShowDetails in the ConvertibleCar class. Le modificateur override est utilisé pour définir ShowDetails dans la classe Minivan.The override modifier is used to define ShowDetails in the Minivan class.

// Define the base class, Car. The class defines two methods,  
// DescribeCar and ShowDetails. DescribeCar calls ShowDetails, and each derived  
// class also defines a ShowDetails method. The example tests which version of  
// ShowDetails is selected, the base class method or the derived class method.  
class Car  
{  
    public void DescribeCar()  
    {  
        System.Console.WriteLine("Four wheels and an engine.");  
        ShowDetails();  
    }  
  
    public virtual void ShowDetails()  
    {  
        System.Console.WriteLine("Standard transportation.");  
    }  
}  
  
// Define the derived classes.  
  
// Class ConvertibleCar uses the new modifier to acknowledge that ShowDetails  
// hides the base class method.  
class ConvertibleCar : Car  
{  
    public new void ShowDetails()  
    {  
        System.Console.WriteLine("A roof that opens up.");  
    }  
}  
  
// Class Minivan uses the override modifier to specify that ShowDetails  
// extends the base class method.  
class Minivan : Car  
{  
    public override void ShowDetails()  
    {  
        System.Console.WriteLine("Carries seven people.");  
    }  
}  

L’exemple vérifie la version de ShowDetails qui est appelée.The example tests which version of ShowDetails is called. La méthode suivante, TestCars1, déclare une instance de chaque classe, puis appelle DescribeCar sur chaque instance.The following method, TestCars1, declares an instance of each class, and then calls DescribeCar on each instance.

public static void TestCars1()  
{  
    System.Console.WriteLine("\nTestCars1");  
    System.Console.WriteLine("----------");  
  
    Car car1 = new Car();  
    car1.DescribeCar();  
    System.Console.WriteLine("----------");  
  
    // Notice the output from this test case. The new modifier is  
    // used in the definition of ShowDetails in the ConvertibleCar  
    // class.
  
    ConvertibleCar car2 = new ConvertibleCar();  
    car2.DescribeCar();  
    System.Console.WriteLine("----------");  
  
    Minivan car3 = new Minivan();  
    car3.DescribeCar();  
    System.Console.WriteLine("----------");  
}  

TestCars1 génère la sortie suivante.TestCars1 produces the following output. Notez en particulier les résultats de car2, qui ne correspondent probablement pas à ce que vous attendiez.Notice especially the results for car2, which probably are not what you expected. Le type de l’objet est ConvertibleCar, mais DescribeCar n’accède pas à la version de ShowDetails qui est défini dans la classe ConvertibleCar, car cette méthode est déclarée avec le modificateur new, et non override.The type of the object is ConvertibleCar, but DescribeCar does not access the version of ShowDetails that is defined in the ConvertibleCar class because that method is declared with the new modifier, not the override modifier. Par conséquent, un objet ConvertibleCar affiche la même description qu’un objet Car.As a result, a ConvertibleCar object displays the same description as a Car object. Comparez les résultats pour car3, qui est un objet Minivan.Contrast the results for car3, which is a Minivan object. Dans ce cas, la méthode ShowDetails déclarée dans la classe Minivan substitue la méthode ShowDetails déclarée dans la classe Car et la description affichée décrit un minivan.In this case, the ShowDetails method that is declared in the Minivan class overrides the ShowDetails method that is declared in the Car class, and the description that is displayed describes a minivan.

// TestCars1  
// ----------  
// Four wheels and an engine.  
// Standard transportation.  
// ----------  
// Four wheels and an engine.  
// Standard transportation.  
// ----------  
// Four wheels and an engine.  
// Carries seven people.  
// ----------  

TestCars2 crée une liste d’objets de type Car.TestCars2 creates a list of objects that have type Car. Les valeurs des objets sont instanciées à partir des classes Car, ConvertibleCar et Minivan.The values of the objects are instantiated from the Car, ConvertibleCar, and Minivan classes. DescribeCar est appelé sur chaque élément de la liste.DescribeCar is called on each element of the list. Le code suivant illustre la définition de TestCars2.The following code shows the definition of TestCars2.

public static void TestCars2()  
{  
    System.Console.WriteLine("\nTestCars2");  
    System.Console.WriteLine("----------");  
  
    var cars = new List<Car> { new Car(), new ConvertibleCar(),
        new Minivan() };  
  
    foreach (var car in cars)  
    {  
        car.DescribeCar();  
        System.Console.WriteLine("----------");  
    }  
}  

La sortie suivante s’affiche.The following output is displayed. Notez qu’elle est identique à la sortie affichée par TestCars1.Notice that it is the same as the output that is displayed by TestCars1. La méthode ShowDetails de la classe ConvertibleCar n’est pas appelée, que le type de l’objet soit ConvertibleCar, comme dans TestCars1, ou Car, comme dans TestCars2.The ShowDetails method of the ConvertibleCar class is not called, regardless of whether the type of the object is ConvertibleCar, as in TestCars1, or Car, as in TestCars2. À l’inverse, car3 appelle la méthode ShowDetails à partir de la classe Minivan dans les deux cas, que son type soit Minivan ou Car.Conversely, car3 calls the ShowDetails method from the Minivan class in both cases, whether it has type Minivan or type Car.

// TestCars2  
// ----------  
// Four wheels and an engine.  
// Standard transportation.  
// ----------  
// Four wheels and an engine.  
// Standard transportation.  
// ----------  
// Four wheels and an engine.  
// Carries seven people.  
// ----------  

Les méthodes TestCars3 et TestCars4 terminent l’exemple.Methods TestCars3 and TestCars4 complete the example. Ces méthodes appellent ShowDetails directement, d’abord à partir des objets déclarés avec le type ConvertibleCar et Minivan (TestCars3), puis à partir des objets déclarés avec le type Car (TestCars4).These methods call ShowDetails directly, first from objects declared to have type ConvertibleCar and Minivan (TestCars3), then from objects declared to have type Car (TestCars4). Le code suivant définit ces deux méthodes.The following code defines these two methods.

public static void TestCars3()  
{  
    System.Console.WriteLine("\nTestCars3");  
    System.Console.WriteLine("----------");  
    ConvertibleCar car2 = new ConvertibleCar();  
    Minivan car3 = new Minivan();  
    car2.ShowDetails();  
    car3.ShowDetails();  
}  
  
public static void TestCars4()  
{  
    System.Console.WriteLine("\nTestCars4");  
    System.Console.WriteLine("----------");  
    Car car2 = new ConvertibleCar();  
    Car car3 = new Minivan();  
    car2.ShowDetails();  
    car3.ShowDetails();  
}  

Les méthodes produisent la sortie suivante, qui correspond aux résultats du premier exemple de cette rubrique.The methods produce the following output, which corresponds to the results from the first example in this topic.

// TestCars3  
// ----------  
// A roof that opens up.  
// Carries seven people.  
  
// TestCars4  
// ----------  
// Standard transportation.  
// Carries seven people.  

Le code suivant illustre le projet complet et sa sortie.The following code shows the complete project and its output.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
  
namespace OverrideAndNew2  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            // Declare objects of the derived classes and test which version  
            // of ShowDetails is run, base or derived.  
            TestCars1();  
  
            // Declare objects of the base class, instantiated with the  
            // derived classes, and repeat the tests.  
            TestCars2();  
  
            // Declare objects of the derived classes and call ShowDetails  
            // directly.  
            TestCars3();  
  
            // Declare objects of the base class, instantiated with the  
            // derived classes, and repeat the tests.  
            TestCars4();  
        }  
  
        public static void TestCars1()  
        {  
            System.Console.WriteLine("\nTestCars1");  
            System.Console.WriteLine("----------");  
  
            Car car1 = new Car();  
            car1.DescribeCar();  
            System.Console.WriteLine("----------");  
  
            // Notice the output from this test case. The new modifier is  
            // used in the definition of ShowDetails in the ConvertibleCar  
            // class.
            ConvertibleCar car2 = new ConvertibleCar();  
            car2.DescribeCar();  
            System.Console.WriteLine("----------");  
  
            Minivan car3 = new Minivan();  
            car3.DescribeCar();  
            System.Console.WriteLine("----------");  
        }  
        // Output:  
        // TestCars1  
        // ----------  
        // Four wheels and an engine.  
        // Standard transportation.  
        // ----------  
        // Four wheels and an engine.  
        // Standard transportation.  
        // ----------  
        // Four wheels and an engine.  
        // Carries seven people.  
        // ----------  
  
        public static void TestCars2()  
        {  
            System.Console.WriteLine("\nTestCars2");  
            System.Console.WriteLine("----------");  
  
            var cars = new List<Car> { new Car(), new ConvertibleCar(),
                new Minivan() };  
  
            foreach (var car in cars)  
            {  
                car.DescribeCar();  
                System.Console.WriteLine("----------");  
            }  
        }  
        // Output:  
        // TestCars2  
        // ----------  
        // Four wheels and an engine.  
        // Standard transportation.  
        // ----------  
        // Four wheels and an engine.  
        // Standard transportation.  
        // ----------  
        // Four wheels and an engine.  
        // Carries seven people.  
        // ----------  
  
        public static void TestCars3()  
        {  
            System.Console.WriteLine("\nTestCars3");  
            System.Console.WriteLine("----------");  
            ConvertibleCar car2 = new ConvertibleCar();  
            Minivan car3 = new Minivan();  
            car2.ShowDetails();  
            car3.ShowDetails();  
        }  
        // Output:  
        // TestCars3  
        // ----------  
        // A roof that opens up.  
        // Carries seven people.  
  
        public static void TestCars4()  
        {  
            System.Console.WriteLine("\nTestCars4");  
            System.Console.WriteLine("----------");  
            Car car2 = new ConvertibleCar();  
            Car car3 = new Minivan();  
            car2.ShowDetails();  
            car3.ShowDetails();  
        }  
        // Output:  
        // TestCars4  
        // ----------  
        // Standard transportation.  
        // Carries seven people.  
    }  
  
    // Define the base class, Car. The class defines two virtual methods,  
    // DescribeCar and ShowDetails. DescribeCar calls ShowDetails, and each derived  
    // class also defines a ShowDetails method. The example tests which version of  
    // ShowDetails is used, the base class method or the derived class method.  
    class Car  
    {  
        public virtual void DescribeCar()  
        {  
            System.Console.WriteLine("Four wheels and an engine.");  
            ShowDetails();  
        }  
  
        public virtual void ShowDetails()  
        {  
            System.Console.WriteLine("Standard transportation.");  
        }  
    }  
  
    // Define the derived classes.  
  
    // Class ConvertibleCar uses the new modifier to acknowledge that ShowDetails  
    // hides the base class method.  
    class ConvertibleCar : Car  
    {  
        public new void ShowDetails()  
        {  
            System.Console.WriteLine("A roof that opens up.");  
        }  
    }  
  
    // Class Minivan uses the override modifier to specify that ShowDetails  
    // extends the base class method.  
    class Minivan : Car  
    {  
        public override void ShowDetails()  
        {  
            System.Console.WriteLine("Carries seven people.");  
        }  
    }  
  
}  

Voir aussiSee also