250 votes

Différence entre nouveau et dérogation

Je me demande quelle est la différence entre les éléments suivants :

Cas 1 : Classe de base

public void DoIt();

Cas 1 : Classe héritée

public new void DoIt();

Cas 2 : Classe de base

public virtual void DoIt();

Cas 2 : Classe héritée

public override void DoIt();

Les cas 1 et 2 semblent avoir le même effet d'après les tests que j'ai effectués. Y a-t-il une différence ou une méthode préférée ?

3 votes

Duplication de nombreuses questions, y compris stackoverflow.com/questions/159978/

323voto

rahul Points 84185

La dérogation modifie et doit être utilisé pour les méthodes abstraites. Ceci indique pour la comp d'une méthode. Même si la méthode est appelée sur une référence à la classe de base, elle utilisera l'implémentation l'implémentation qui la remplace.

public class Base
{
    public virtual void DoIt()
    {
    }
}

public class Derived : Base
{
    public override void DoIt()
    {
    }
}

Base b = new Derived();
b.DoIt();                      // Calls Derived.DoIt

appellera Derived.DoIt si cela l'emporte sur Base.DoIt .

Le nouveau modificateur indique au compilateur d'utiliser l'implémentation de votre classe enfant au lieu de l'implémentation de la classe mère de la classe mère. Tout code qui n'est pas référençant votre classe mais la classe utilisera l'implémentation de la classe parentale de la classe parente.

public class Base
{
    public virtual void DoIt()
    {
    }
}

public class Derived : Base
{
    public new void DoIt()
    {
    }
}

Base b = new Derived();
Derived d = new Derived();

b.DoIt();                      // Calls Base.DoIt
d.DoIt();                      // Calls Derived.DoIt

Premier appel Base.DoIt alors Derived.DoIt . Il s'agit en fait de deux méthodes entièrement distinctes qui portent le même nom, plutôt que d'une méthode dérivée qui surcharge la méthode de base.

Fuente: Blog de Microsoft

5 votes

This indicates for the compiler to use the last defined implementation of a method . comment trouver la dernière implémentation définie d'une méthode ?

6 votes

En partant d'une classe concrète, vérifiez si elle possède une implémentation de la méthode qui vous intéresse. Si c'est le cas, vous avez terminé. Si ce n'est pas le cas, remontez d'un cran dans la hiérarchie de l'héritage, c'est-à-dire vérifiez si la super-classe possède la méthode en question. Continuez jusqu'à ce que vous ayez trouvé la méthode en question.

3 votes

Notez également que vous ne pouvez override une méthode lorsque la classe de base définit la méthode en tant que virtual . Le mot virtual est la classe de base qui dit "Hé, quand j'appelle cette méthode, elle pourrait virtuellement avoir été remplacée par une implémentation dérivée, donc je ne sais pas vraiment à l'avance quelle implémentation de méthode j'appelle réellement au moment de l'exécution". C'est pourquoi virtual signifie qu'il s'agit d'un espace réservé pour une méthode. Cela implique que les méthodes qui ne sont pas marquées comme virtual ne peut pas être remplacée. Mais vous pouvez remplacer toute méthode non virtuelle dans une classe dérivée avec le modificateur new , uniquement accessible au niveau dérivé.

194voto

Jon B Points 26872

virtuel : indique qu'une méthode peut être remplacée par un héritier

surpasser La méthode virtuelle : remplace la fonctionnalité d'une méthode virtuelle dans une classe de base, en fournissant une fonctionnalité différente.

nouveau : cache la méthode originale (qui n'a pas besoin d'être virtuelle), offrant une fonctionnalité différente. Cette méthode ne doit être utilisée qu'en cas d'absolue nécessité.

Lorsque vous cachez une méthode, vous pouvez toujours accéder à la méthode d'origine en faisant appel à la classe de base. C'est utile dans certains cas, mais dangereux.

3 votes

Pourquoi le up casting d'une méthode qui cache la méthode de base est-il dangereux ? Ou êtes-vous en train d'insinuer que le up casting en général est dangereux ?

4 votes

@Mark - un appelant pourrait ne pas être au courant de l'implémentation, ce qui entraînerait une mauvaise utilisation accidentelle.

0 votes

Pouvez-vous utiliser override et/ou new sans virtual sur la méthode parentale ?

21voto

tvanfosson Points 268301

Dans le premier cas, vous cachez la définition dans la classe mère. Cela signifie qu'elle ne sera invoquée que lorsque vous traiterez l'objet en tant que classe enfant. Si la classe est convertie en son type parent, c'est la méthode du parent qui sera invoquée. Dans le second cas, la méthode est surchargée et sera invoquée indépendamment du fait que l'objet soit casté en tant que classe enfant ou parent.

8voto

Yossarian Points 8601

Essayez ce qui suit : (cas1)

((BaseClass)(new InheritedClass())).DoIt()

Edit : virtual+override sont résolus au moment de l'exécution (donc override remplace réellement les méthodes virtuelles), alors que new crée simplement une nouvelle méthode avec le même nom, et cache l'ancienne, c'est résolu au moment de la compilation -> votre compilateur appellera la méthode qu'il "voit".

4voto

Matthew Whited Points 12255

Dans le cas 1, si vous appelez la méthode DoIt() de la classe héritée alors que le type est déclaré comme classe de base, vous verrez l'action de la classe de base.

/* Results
Class1
Base1
Class2
Class2
*/
public abstract class Base1
{
    public void DoIt() { Console.WriteLine("Base1"); }
}
public  class Class1 : Base1 
{
    public new void DoIt() { Console.WriteLine("Class1"); }
}
public abstract class Base2
{
    public virtual void DoIt() { Console.WriteLine("Base2"); }
}
public class Class2 : Base2
{
    public override void DoIt() { Console.WriteLine("Class2"); }
}
static void Main(string[] args)
{
    var c1 = new Class1();
    c1.DoIt();
    ((Base1)c1).DoIt();

    var c2 = new Class2();
    c2.DoIt();
    ((Base2)c2).DoIt();
    Console.Read();
}

0 votes

Pourriez-vous afficher l'avertissement ou l'erreur que vous recevez ? Ce code fonctionnait correctement lorsque je l'ai posté à l'origine.

0 votes

Tout cela doit être collé dans la classe de votre point d'entrée (Programme). Cette dernière a été supprimée pour permettre une meilleure mise en forme sur ce site.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X