Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
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. Vous pouvez spécifier comment les méthodes interagissent en utilisant les mots-clés new et override. Le override
modificateur étend la méthode de classe virtual
de base et le new
modificateur masque une méthode de classe de base accessible. La différence est illustrée dans les exemples de cette rubrique.
Dans une application console, déclarez les deux classes suivantes et BaseClass
DerivedClass
.
DerivedClass
hérite de BaseClass
.
class BaseClass
{
public void Method1()
{
Console.WriteLine("Base - Method1");
}
}
class DerivedClass : BaseClass
{
public void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
Dans la Main
méthode, déclarez des variables bc
, dc
et bcdc
.
bc
est de typeBaseClass
, et sa valeur est de typeBaseClass
.dc
est de typeDerivedClass
, et sa valeur est de typeDerivedClass
.bcdc
est de typeBaseClass
, et sa valeur est de typeDerivedClass
. Il s’agit de la variable à prendre en compte.
Comme bc
et bcdc
ont le type BaseClass
, ils ne peuvent accéder directement qu’à Method1
, sauf si vous effectuez un cast. La variable dc
peut accéder aux deux Method1
et Method2
. Ces relations sont indiquées dans le code suivant.
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 suivante Method2
à BaseClass
. La signature de cette méthode correspond à la signature de la Method2
méthode dans DerivedClass
.
public void Method2()
{
Console.WriteLine("Base - Method2");
}
Étant donné que BaseClass
maintenant a une Method2
méthode, une deuxième instruction appelante peut être ajoutée pour BaseClass
les variables bc
et bcdc
, comme illustré dans le code suivant.
bc.Method1();
bc.Method2();
dc.Method1();
dc.Method2();
bcdc.Method1();
bcdc.Method2();
Lorsque vous générez le projet, vous voyez que l’ajout de la méthode Method2
dans BaseClass
provoque un avertissement. L’avertissement indique que la Method2
méthode dans DerivedClass
masque la Method2
méthode dans BaseClass
. Vous êtes invité à utiliser le new
mot clé dans la Method2
définition si vous avez l’intention de provoquer ce résultat. Vous pouvez également renommer l’une des Method2
méthodes pour résoudre l’avertissement, mais ce n’est pas toujours pratique.
Avant d’ajouter new
, exécutez le programme pour voir la sortie produite par les instructions d’appel supplémentaires. Les résultats suivants sont affichés.
// Output:
// Base - Method1
// Base - Method2
// Base - Method1
// Derived - Method2
// Base - Method1
// Base - Method2
Le new
mot-clé conserve les relations qui produisent ce résultat, mais supprime l’avertissement. 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 de DerivedClass
en premier, et ensuite considère les membres hérités de BaseClass
.
Pour supprimer l’avertissement, ajoutez le modificateur new
à la définition de Method2
dans DerivedClass
, comme indiqué dans le code suivant. Le modificateur peut être ajouté avant ou après public
.
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
Réexécutez le programme pour vérifier que la sortie n’a pas changé. Vérifiez également que l’avertissement n’apparaît plus. En utilisant new
, vous affirmez que vous savez que le membre qu’il modifie masque un membre hérité de la classe de base. Pour plus d’informations sur le masquage de nom par héritage, consultez new, modificateur.
Pour comparer ce comportement aux effets de l’utilisation override
, ajoutez la méthode suivante à DerivedClass
. Le override
modificateur peut être ajouté avant ou après public
.
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
Ajoutez le modificateur virtual
à la définition de Method1
dans BaseClass
. Le virtual
modificateur peut être ajouté avant ou après public
.
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
Réexécutez le projet. Notez en particulier les deux dernières lignes de la sortie suivante.
// Output:
// Base - Method1
// Base - Method2
// Derived - Method1
// Derived - Method2
// Derived - Method1
// Base - Method2
L’utilisation du override
modificateur permet bcdc
d’accéder à la Method1
méthode définie dans DerivedClass
. En règle générale, il s’agit du comportement souhaité dans les hiérarchies d’héritage. Vous souhaitez que les objets qui ont des valeurs créées à partir de la classe dérivée utilisent les méthodes définies dans la classe dérivée. Vous obtenez ce comportement en utilisant override
pour étendre la méthode de classe de base.
Le code suivant contient l’exemple complet.
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 contexte différent. L’exemple définit trois classes : une classe de base nommée Car
et deux classes dérivées de celle-ci, ConvertibleCar
et Minivan
. La classe de base contient une DescribeCar
méthode. La méthode affiche une description de base d’une voiture, puis appelle ShowDetails
pour fournir des informations supplémentaires. Chacune des trois classes définit une ShowDetails
méthode. Le new
modificateur est utilisé pour définir ShowDetails
dans la ConvertibleCar
classe. Le override
modificateur est utilisé pour définir ShowDetails
dans la Minivan
classe.
// 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 teste quelle version de ShowDetails
est appelée. La méthode suivante, TestCars1
déclare une instance de chaque classe, puis appelle DescribeCar
sur chaque 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
produit la sortie suivante. Notez en particulier les résultats pour car2
, qui ne sont probablement pas ce que vous attendiez. Le type de l’objet est ConvertibleCar
, mais DescribeCar
n’accède pas à la version de ShowDetails
celle-ci définie dans la ConvertibleCar
classe, car cette méthode est déclarée avec le new
modificateur, et non le override
modificateur. Par conséquent, un ConvertibleCar
objet affiche la même description qu’un Car
objet. Contrastez les résultats pour car3
, qui est un Minivan
objet. Dans ce cas, la ShowDetails
méthode déclarée dans la Minivan
classe remplace la ShowDetails
méthode déclarée dans la Car
classe et la description affichée décrit un 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 qui ont le type Car
. Les valeurs des objets sont instanciées à partir des classes Car
, ConvertibleCar
, et Minivan
.
DescribeCar
est appelé sur chaque élément de la liste. Le code suivant montre la définition de 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. Notez qu’il est identique à la sortie affichée par TestCars1
. La ShowDetails
méthode de la ConvertibleCar
classe n’est pas appelée, que le type de l’objet soit ConvertibleCar
, comme dans TestCars1
, ou Car
, comme dans TestCars2
.
car3
À l'inverse, dans les deux cas, appelle la méthode ShowDetails
de la classe Minivan
, qu'elle soit de type Minivan
ou de 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.
// ----------
Méthodes TestCars3
et TestCars4
complètent l'exemple. Ces méthodes appellent ShowDetails
directement, d’abord à partir d’objets déclarés pour avoir le type ConvertibleCar
et Minivan
(TestCars3
), puis à partir d’objets déclarés pour avoir le type Car
(TestCars4
). Le code suivant définit ces deux méthodes.
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.
// TestCars3
// ----------
// A roof that opens up.
// Carries seven people.
// TestCars4
// ----------
// Standard transportation.
// Carries seven people.
Le code suivant montre le projet complet et sa sortie.
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.");
}
}
}