C# che chiama metodi della sottoclasse sottoposti a override senza sapere che si tratta di un'istanza della sottoclasse
-
23-08-2019 - |
Domanda
Ho una classe base con un metodo virtuale e più sottoclassi che sovrascrivono quel metodo.
Quando incontro una di queste sottoclassi, vorrei chiamare il metodo sovrascritto, ma senza conoscere la sottoclasse.Mi vengono in mente modi brutti per farlo (controllare un valore e lanciarlo), ma sembra che dovrebbe esserci un modo nel linguaggio per farlo.Voglio che la Lista contenga più sottoclassi all'interno della stessa lista, altrimenti ovviamente potrei semplicemente creare una Lista.
MODIFICARE:Risolto il commento nel codice sbagliato, che ha portato alla prima risposta molto appropriata che ho ricevuto :)
Ad esempio:
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
}
Soluzione
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
}
Altri suggerimenti
Perché dovrebbe stampare "Pippo"? Questo non è lo scopo di metodi virtuali. Il punto è che le classi derivate possono cambiare il modo in cui la funzione lavora senza cambiare l'interfaccia. Un oggetto Foo stamperà "Foo" e un oggetto bar stamperà "Bar". Tutto il resto sarebbe sbagliato.
Utilizzare il nuovo modificatore per nascondere in modo esplicito un membro ereditato da una classe base. Per nascondere un membro ereditato, dichiararla nella classe derivata utilizzando lo stesso nome, e modificarlo con il nuovo modificatore. Questo si tradurrà in esattamente il comportamento che si desidera.
Per maggiori informazioni vai qui: http://geekswithblogs.net/Mohamed/articles/28613 aspx
Per ottenere il comportamento desiderato in questa situazione è possibile rimuovere il virtuale sulla classe di base e utilizzare nuovi della sottoclasse.
Tuttavia, come Ed Swangren indicato, perché dovresti?
Non esiste una soluzione in cui lanci semplicemente l'oggetto che vuoi chiamare l'altro:
foo.printMe(); // prints FOO.. Would like it to print BAR
diventa
(Foo)foo.printMe(); // foo can be any derived class of Foo.
Oppure mi sto perdendo qualche parte della domanda?