2008-12-23 8 views
4

J'ai une classe de base avec une méthode virtuelle et plusieurs sous-classes qui remplacent cette méthode.C# appelant des méthodes de sous-classe surchargées sans savoir qu'il s'agit d'une instance de sous-classe

Lorsque je rencontre l'une de ces sous-classes, je voudrais appeler la méthode substituée, mais sans connaître la sous-classe. Je peux penser à des façons laides de le faire (vérifier une valeur et la jeter), mais il semble qu'il devrait y avoir une façon de le faire dans la langue. Je veux que la liste contienne plusieurs sous-classes dans la même liste, sinon je pourrais simplement faire une liste.

EDIT: Correction du commentaire dans le code qui a eu tort, ce qui conduit à la première réponse très appropriée, je suis :)

Par exemple:

Class Foo 
{ 
    public virtual printMe() 
    { 
     Console.Writeline("FOO"); 
    } 
} 

Class Bar : Foo 
{ 
    public override printMe() 
    { 
     Console.Writeline("BAR"); 
    } 
} 

List<Foo> list = new List<Foo>(); 
// then populate this list with various 'Bar' and other overriden Foos 

foreach (Foo foo in list) 
{ 
    foo.printMe(); // prints FOO.. Would like it to print BAR 
} 
+0

Comment est-ce qu'il imprime Foo, s'il s'agit d'une classe dérivée remplaçant une méthode virtuelle? Typo dans votre exemple de code? – mmcrae

Répondre

8
class Foo 
{ 
    public virtual void virtualPrintMe() 
    { 
     nonVirtualPrintMe(); 
    } 

    public void nonVirtualPrintMe() 
    { 
     Console.Writeline("FOO"); 
    } 
} 

class Bar : Foo 
{ 
    public override void virtualPrintMe() 
    { 
     Console.Writeline("BAR"); 
    } 
} 

List<Foo> list = new List<Foo>(); 
// then populate this list with various 'Bar' and other overriden Foos 

foreach (Foo foo in list) 
{ 
    foo.virtualPrintMe(); // prints BAR or FOO 
    foo.nonVirtualPrintMe(); // always prints FOO 
} 
+0

C'est le comportement que je voulais mais je n'obtenais pas .. Mon problème s'est avéré être de charger les anciens objets sérialisés qui étaient de l'ancien type de classe de base, plutôt que la nouvelle sous-classe. –

1

Pourquoi faut-il imprimer « Foo »? Ce n'est pas le but des méthodes virtuelles. Tout le problème est que les classes dérivées peuvent changer la façon dont la fonction fonctionne sans changer l'interface. Un objet Foo affichera "Foo" et un objet Bar affichera "Bar". Tout le reste aurait tort.

+0

Vous avez absolument raison. J'ai eu un bug dans le commentaire de l'extrait que j'ai posté à l'origine. Il appelle la méthode de la classe de base, vraisemblablement parce qu'elle ne sait pas qu'il s'agit d'une instance sous-classée. –

0

Utilisez le nouveau modificateur pour masquer explicitement un membre hérité d'une classe de base. Pour masquer un membre hérité, déclarez-le dans la classe dérivée en utilisant le même nom et modifiez-le avec le nouveau modificateur. Cela entraînera exactement le comportement que vous voulez.

Pour plus d'informations rendez-vous ici: http://geekswithblogs.net/Mohamed/articles/28613.aspx

0

Pour obtenir le comportement que vous voulez dans cette situation, vous pouvez supprimer le virtuel sur la classe de base et utiliser les nouvelles sur la sous-classe.

Toutefois, comme Ed Swangren l'a indiqué, pourquoi le feriez-vous?

0

est pas là une solution où vous venez lancez l'objet que vous voulez appeler l'autre:

foo.printMe(); // prints FOO.. Would like it to print BAR 

devient

(Foo)foo.printMe(); // foo can be any derived class of Foo. 

Ou suis-je manque une partie de la question?

+1

Ce second appelait printMe et essayait de convertir la valeur de retour en (Foo). Et ça revient vide. –

+0

Ah, désolé j'ai raté un ensemble de parenthèses, la deuxième ligne devrait être ((Foo) foo) .printMe(); cela devrait retourner foo car il jette l'objet, puis fait l'appel. –

Questions connexes