En C #, que signifie le terme shadowing? J'ai lu ce lien mais je ne l'ai pas bien compris.
Shadowing cache une méthode dans une classe de base. En utilisant l'exemple de la question que vous avez liée:
class A
{
public int Foo(){ return 5;}
public virtual int Bar(){return 5;}
}
class B : A
{
public new int Foo() { return 1;}
public override int Bar() {return 1;}
}
La classe B
remplace la méthode virtuelle Bar
. Il cache (ombres) la méthode non virtuelle Foo
. La substitution utilise le mot-clé override . L'observation est effectuée avec le mot-clé new .
Dans le code ci-dessus, si vous n'avez pas utilisé le mot clé new lors de la définition de la méthode Foo
dans la classe B
, vous obtiendrez cet avertissement du compilateur:
'test.B.Foo()' hides inherited member 'test.A.Foo()'. Use the new keyword if hiding was intended.
Supposons que j'ai une classe de base qui implémente une méthode virtuelle:
public class A
{
public virtual void M() { Console.WriteLine("In A.M()."); }
}
J'ai aussi une classe dérivée qui définit également une méthode M:
public class B : A
{
// could be either "new" or "override", "new" is default
public void M() { Console.WriteLine("In B.M()."); }
}
Supposons maintenant que j'écris un programme comme celui-ci:
A alpha = new B(); // it's really a B but I cast it to an A
alpha.M();
J'ai deux choix différents quant à la manière dont je souhaite que cela soit mis en œuvre. Le comportement par défaut consiste à appeler la version de M. de A (ce comportement est identique si vous avez appliqué le mot clé "new
" à B.M()
.)
Cela s'appelle "shadowing" quand nous avons une méthode avec le même nom mais un comportement différent quand elle est appelée depuis la classe de base.
Alternativement, nous aurions pu spécifier "override
" sur B.M()
. Dans ce cas, alpha.M()
aurait appelé la version de M. de B.
L’observation consiste à masquer une méthode de classe de base avec une nouvelle définition dans une classe enfant.
La différence entre masquer et annuler dépend de la façon dont les méthodes sont appelées.
Ainsi, lorsqu'une méthode virtuelle est remplacée, l'adresse d'appel de la table d'appel de méthode de la classe de base est remplacée par l'adresse de la routine enfant.
En revanche, lorsqu'une méthode est masquée, une nouvelle adresse est ajoutée à la table d'appels à la méthode de la classe enfant.
Lorsqu'un appel est fait à la méthode en question:
Si nous appelons la méthode avec une référence à la classe enfant alors le comportement est le même, si la méthode a été remplacée, l'adresse de la méthode sera trouvée dans la classe de base, si la méthode est masquée, l'adresse de la méthode sera trouvée sur le classe enfant, et comme elle a déjà été trouvée, la table de classe de base ne fera pas l'objet d'une recherche.
Si nous appelons la méthode avec une référence à la classe de base, le comportement change. Lors de la substitution, l'adresse de la méthode écrasant l'entrée de la classe de base, nous appellerons la méthode enfant, même si vous tenez une référence à la classe de base. Avec shadowing, la table de méthode de la classe de base (qui est la seule visible car nous tenons une référence à la classe de base) contient l'adresse de la méthode virtuelle et, par conséquent, la méthode de la classe de base sera appelée.
En général, l'observation est une mauvaise idée, car elle introduit une différence dans le comportement d'une instance en fonction de la référence que nous avons à celle-ci.
Développer la bonne réponse de Kent
Quand je ne sais pas quand la méthode sera appelée, j’aime penser à l’observation par rapport à l’annulation suivante
Voici un article MSDN sur Shadowing. Les exemples de langage sont en Visual Basic (malheureusement, il n’ya pas de page C # équivalente sur MSDN), mais elle traite généralement des concepts et devrait vous aider à comprendre quand même.
Edit: On dirait qu'il y a est un article C # sur l'observation, à l'exception du fait qu'il s'appelle masquage en C #. En outre, cette page offre un bon aperçu.
Si vous souhaitez masquer la méthode de la classe de base, utilisez override in base [méthode virtuelle dans base]
si vous souhaitez masquer la méthode de classe enfant, utilisez new in base [méthode non virtuelle à base] -> shadow
Base B=new Child()
B.VirtualMethod()
-> Appelle la méthode de classe enfant
B.NonVirtualMethod()
-> Appelle la méthode de la classe de base
Remplacement : même nom et exactement les mêmes paramètres, implémentés différemment dans les sous-classes.
Shadowing : même nom et exactement les mêmes paramètres, implémentés différemment dans les sous-classes.
J'espère que cette brève explication aide.Shadowing
- Remplace l'élément complet de la classe parente
class InventoryAndSales
{
public int InvoiceNumber { get; set; }
}
//if someone calls for this class then the InvoiceNumber type is now object
class NewInventoryAndSales : InventoryAndSales
{
public new object InvoiceNumber { get; set; }
}
Overriding
- Ne remplace que l'implémentation. Il ne remplace pas le type de données qu'il ne remplace pas, comme par exemple si vous avez une variable, il ne la convertit pas en méthode. Ainsi, s'il existe une méthode, elle utilisera cette méthode et ne modifiera que l'implémentation.
class InventoryAndSales
{
public virtual int GetTotalSales(int a, int b)
{
return a + b;
}
}
class NewInventoryAndSales : InventoryAndSales
{
//it replaces the implementation in parent class
public override int GetTotalSales(int a, int b)
{
return a * b;
}
}