Risposte:
Bene eredità ...
supponi di avere queste classi:
class A {
public int Foo(){ return 5;}
public virtual int Bar(){return 5;}
}
class B : A{
public new int Foo() { return 1;} //shadow
public override int Bar() {return 1;} //override
}
poi quando lo chiami:
A clA = new A();
B clB = new B();
Console.WriteLine(clA.Foo()); // output 5
Console.WriteLine(clA.Bar()); // output 5
Console.WriteLine(clB.Foo()); // output 1
Console.WriteLine(clB.Bar()); // output 1
//now let's cast B to an A class
Console.WriteLine(((A)clB).Foo()); // output 5 <<<-- shadow
Console.WriteLine(((A)clB).Bar()); // output 1
Supponiamo di avere una classe di base e di utilizzare la classe di base in tutto il codice invece delle classi ereditate e di utilizzare shadow, restituirà i valori restituiti dalla classe di base invece di seguire l'albero di ereditarietà del tipo reale dell'oggetto.
Spero di avere un senso :)
Lo shadowing è in realtà il linguaggio VB per ciò che chiameremmo nascosto in C #.
Spesso l'occultamento (ombreggiamento in VB) e l'override vengono mostrati come risposta da Stormenet .
Un metodo virtuale viene mostrato come sovrascritto da una sottoclasse e le chiamate a quel metodo anche sul tipo di superclasse o dall'interno del codice della superclasse chiameranno l'implementazione sostitutiva dalla sottoclasse.
Quindi viene mostrato un metodo concreto (uno non contrassegnato come virtuale o astratto) nascosto utilizzando la newparola chiave quando si definisce un metodo con una firma identica nella sottoclasse. In questo caso, quando il metodo viene chiamato sul tipo di superclasse, viene utilizzata l'implementazione originale, la nuova implementazione è disponibile solo sulla sottoclasse.
Tuttavia ciò che spesso manca è che è anche possibile nascondere un metodo virtuale.
class A
{
public virtual void DoStuff() { // original implementation }
}
class B : A
{
public new void DoStuff() { //new implementation }
}
B b = new B();
A a = b;
b.DoStuff(); //calls new implementation
a.DoStuff(); //calls original implementation.
Nota nell'esempio sopra DoStuff diventa concreto e non può essere sovrascritto. Tuttavia è anche possibile utilizzare sia il virtuale newle parole chiave insieme.
class A
{
public virtual void DoStuff() { // original implementation }
}
class B : A
{
public new virtual void DoStuff() { //new implementation }
}
class C : B
{
public override void DoStuff() { //replacement implementation }
}
C c = new C();
B b = c;
A a = b;
c.DoStuff(); //calls replacement implementation
b.DoStuff(); //calls replacement implementation
a.DoStuff(); //calls original implementation.
Si noti che nonostante tutti i metodi coinvolti siano virtuali, l'override su C non influisce sul metodo virtuale su A perché l'uso di newin B nasconde l'implementazione A.
Modifica: è stato notato nei commenti a questa risposta che quanto sopra potrebbe essere pericoloso o almeno non particolarmente utile. Direi di sì, può essere pericoloso e sarebbe là fuori se fosse del tutto utile.
In particolare potresti finire nei guai di ogni tipo se modifichi anche i modificatori dell'accessibilità. Per esempio:-
public class Foo
{
internal Foo() { }
protected virtual string Thing() { return "foo"; }
}
public class Bar : Foo
{
internal new string Thing() { return "bar"; }
}
Per un erede esterno di Bar, Fool'implementazione di Thing () rimane accessibile e sovrascrivibile. Tutto legale e spiegabile secondo le regole del tipo .NET, mai del tutto inconsistente.
Ho pubblicato questa risposta per approfondire la comprensione di come funzionano le cose non come suggerimento di tecniche che possono essere utilizzate liberamente.
Penso che la differenza principale sia che con lo shadowing, stai essenzialmente riutilizzando il nome e ignorando semplicemente l'uso della superclasse. Con l'override, stai cambiando l'implementazione, ma non l'accessibilità e la firma (es. Tipi di parametro e ritorno). Vedi http://www.geekinterview.com/question_details/19331 .
Lo shadowing è un concetto di VB.NET. In C #, lo shadowing è noto come Hiding. Nasconde il metodo della classe derivata. Si ottiene utilizzando la parola chiave "nuovo".
La parola chiave Override viene utilizzata per fornire un'implementazione completamente nuova di un metodo della classe base (che è contrassegnato come "Virtual") nella classe derivata.
Fondamentalmente se hai qualcosa come sotto,
Class A
{
}
Class B:A
{
}
A a = new B();
Qualsiasi metodo che chiami sull'oggetto 'a' sarà fatto sul tipo 'a' (qui il tipo è 'A') Ma se implementi lo stesso metodo nella classe B che è già presente nella classe A, il compilatore lo farà ti avvisa di utilizzare una parola chiave "Nuova". Se utilizzi "Nuovo", l'avviso scomparirà. Oltre a questo, non c'è differenza tra l'utilizzo di "New" o il non utilizzo nella classe ereditata.
In alcune situazioni potrebbe essere necessario chiamare un metodo della classe di riferimento che la particolare istanza contiene in quel momento invece di chiamare un metodo sul tipo di oggetto. Nel caso precedente il riferimento che contiene è "B", ma il tipo è "A". Quindi, se si desidera che la chiamata al metodo avvenga su "B", utilizzare Virtual e eseguire l'override per ottenere ciò.
Spero che questo ti aiuti...
Daniel Sandeep.
Se c'è un caso in cui non puoi alterare il contenuto di una classe, diciamo A, ma vuoi usare i suoi metodi insieme a un metodo il cui nome è comune, puoi usare la tua implementazione del metodo con la newparola chiave.
Il punto cruciale è che sia il riferimento che l'oggetto devono essere dello stesso tipo.
class A
{
public void Test()
{
Console.WriteLine("base");
}
}
class B : A
{
public new void Test()
{
Console.WriteLine("sub");
}
public static void Main(string[] args)
{
A a = new A();
B aa = new B();
a.Test();
aa.Test();
}
}