avantage d’utiliser un nouveau mot clé dans un membre de classe dérivé ayant le même nom avec un membre de classe de base

La spécification du langage C # indique que si j’hérite d’une classe et que la classe de base et la classe dérivée ont le même membre nommé avec la même signature, je dois utiliser le new mot-clé pour masquer le membre de la classe de base (il existe un autre moyen mot-clé virtual et override dans les membres de classe de base et dérivés).

Mais dans la pratique, j’ai trouvé que la classe dérivée masquait automatiquement le membre dérivé si elle avait le même membre nommé. Quel est donc le principal avantage et le nouveau problème du nouveau mot clé dans le même membre de la classe dérivée?

Nouveau n’est pas nécessaire , comme vous le notez. C’est facultatif , et si vous ne l’utilisez pas, vous recevez un avertissement. Vous avez parfaitement raison de noter qu’il s’agit au premier abord d’une décision de conception étrange.

Le but de cette décision de conception est d’aider à atténuer une classe de problèmes connue sous le nom de problèmes de “classe de base fragile”. Voici une version de ce problème:

Foo Corporation crée une classe Frobber et l’expédie dans Foo.DLL version 1.0:

 namespace FooCorp { public class Frobber { public void Frobnicate() { ... } ... 

Bar Corporation, pour qui vous travaillez, fabrique Blobbers. Un Blobber peut faire tout ce qu’un Frobber peut faire, mais en plus, il peut aussi Blobnicate. Vous décidez donc de réutiliser l’implémentation de Frobnicate de FooCorp et d’append des fonctionnalités supplémentaires:

 namespace BarCorp { public class Blobber : FooCorp.Frobber { public void Blobnicate() { ... } ... 

Foo Corporation se rend compte que les gens aiment Blobnicate et décident d’expédier Foo.DLL v2.0:

 namespace FooCorp { public class Frobber { public void Frobnicate() { ... } public void Blobnicate() { ... } ... 

Lorsque vous obtenez une nouvelle version de Foo.DLL et que vous le recomstackz, vous souhaitez être informé que vous introduisez maintenant accidentellement une nouvelle méthode qui masque une méthode de classe de base. C’est peut-être une chose dangereuse à faire. votre classe a été écrite avec l’hypothèse que la classe de base était un Frobnicator, mais apparemment maintenant, c’est aussi un Blobnicator! Cela pourrait briser vos clients, qui pourraient appeler accidentellement la version de la classe de base alors qu’ils avaient l’intention d’appeler votre version de la classe dérivée.

Nous rendons “new” facultatif afin qu’il soit légal pour vous de suivre une méthode de classe de base sans changer votre code source. Si nous l’avions rendu illégal, FooCorp aurait cassé votre construction avec leur mise à niveau. Mais nous en faisons un avertissement afin que vous sachiez que vous le faites peut-être par accident . Vous pouvez ensuite examiner le code avec soin. si vous décidez que votre implémentation de Blobnicate est maintenant redondante, vous pouvez la supprimer. S’il est toujours bon, vous pouvez le marquer comme “nouveau” et éliminer l’avertissement.

Avoir un sens? C’est l’une des fonctionnalités subtiles de C # qui le rend adapté aux logiciels orientés composants multi-versions à grande échelle.

L’avantage d’utiliser new est de clarifier votre intention.

Cependant, à moins que vous n’ayez vraiment besoin de masquer le membre, il est généralement préférable d’utiliser virtual/override afin d’utiliser le membre de manière polymorphe. En masquant, le new membre est utilisé uniquement via la référence de la classe dérivée. Si vous travaillez via une référence de base, vous continuerez à avoir le comportement de base, ce qui peut être inattendu.

 class Foo { public void M() { Console.WriteLine("Foo"); } } class Bar : Foo { public new void M() { Console.WriteLine("Bar"); } } Bar bar = new Bar(); bar.M(); // writes Bar Foo foo = new Bar(); // still an instance of Bar foo.M(); // writes Foo, does not use "new" method defined in Bar 

Si, à la place, la méthode avait été déclarée avec virtual dans Foo et override dans Bar , l’appel de la méthode aurait toujours été “Bar”, dans les deux cas.

Le new mot-clé vous permet d’être précis dans votre intention.

Bien que le comportement par défaut consiste à masquer le membre de la classe de base sans le nouveau mot-clé, il est impossible d’indiquer si vous souhaitez réellement masquer le membre ou si vous souhaitez réellement le remplacer.

C’est toujours mieux d’être explicite. De cette façon, le prochain développeur saura exactement ce que vous voulez faire.

J’ai créé la méthode CardNumber dans la classe creditCard et ensuite si je souhaite apporter des modifications à la même méthode, c’est-à-dire que j’utilise actuellement le numéro de carte comme combinaison de chaîne et de chaîne renvoyée, mais après que le client ait besoin du numéro de carte entier, vous pouvez utiliser une nouvelle clé. mot ou méthode se cachant sans changer de code.

  class CreditCard { public ssortingng CardNumber(ssortingng value) { return "XXX57879"; } } class GoldCard : CreditCard { public new int CardNumber(ssortingng value) { return 1234567; } }