Odpowiedzi:
Cóż, dziedziczenie ...
załóżmy, że masz te zajęcia:
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
}
wtedy kiedy zadzwonisz do tego:
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
Załóżmy, że masz klasę bazową i używasz klasy bazowej w całym kodzie zamiast klas dziedziczonych i używasz shadow, zwróci on wartości zwracane przez klasę bazową zamiast podążać za drzewem dziedziczenia rzeczywistego typu obiektu.
Mam nadzieję, że mam sens :)
Cieniowanie jest w rzeczywistości językiem VB dla tego, co nazwalibyśmy ukrywaniem w C #.
Często ukrywanie (shadowing w VB) i nadpisywanie są pokazane, jak w odpowiedzi Stormenet .
Pokazuje się, że metoda wirtualna jest zastępowana przez podklasę i wywołania tej metody nawet w typie nadklasy lub z kodu wewnętrznego superklasy będą wywoływać implementację zastępującą z podklasy.
Następnie pokazywana jest konkretna metoda (nie oznaczona jako wirtualna ani abstrakcyjna) ukryta za pomocą newsłowa kluczowego podczas definiowania metody z identycznym podpisem w podklasie. W tym przypadku, gdy metoda jest wywoływana w typie superklasy, używana jest oryginalna implementacja, nowa implementacja jest dostępna tylko w podklasie.
Jednak często pomija się fakt, że można również ukryć metodę wirtualną.
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.
Uwaga w powyższym przykładzie DoStuff staje się konkretny i nie można go zastąpić. Możliwe jest jednak również jednoczesne użycie słów kluczowych virtuali new.
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.
Należy zauważyć, że pomimo tego, że wszystkie metody są wirtualne, przesłonięcie w C nie wpływa na metodę wirtualną w A, ponieważ użycie neww B powoduje ukrycie implementacji A.
Edycja: W komentarzach do tej odpowiedzi zauważono, że powyższe może być niebezpieczne lub przynajmniej niezbyt przydatne. Powiedziałbym, że tak, może to być niebezpieczne i byłoby tam, gdyby było w ogóle przydatne.
W szczególności możesz wpaść w różnego rodzaju kłopoty, jeśli zmienisz również modyfikatory dostępności. Na przykład:-
public class Foo
{
internal Foo() { }
protected virtual string Thing() { return "foo"; }
}
public class Bar : Foo
{
internal new string Thing() { return "bar"; }
}
Do zewnętrznego dziedzica Bar, Foojest realizacja rzecz () pozostaje dostepne i przeciążać. Wszystko to jest zgodne z prawem i możliwe do wyjaśnienia zgodnie z regułami typu .NET.
Opublikowałem tę odpowiedź, aby pogłębić zrozumienie, jak działają rzeczy, a nie jako sugestię technik, z których można swobodnie korzystać.
Myślę, że główna różnica polega na tym, że w przypadku cieniowania zasadniczo ponownie używasz nazwy i po prostu ignorujesz użycie superklasy. Przy zastępowaniu zmieniasz implementację, ale nie dostępność i sygnaturę (np. Typy parametrów i zwrot). Zobacz http://www.geekinterview.com/question_details/19331 .
Shadowing to koncepcja VB.NET. W C # cieniowanie jest znane jako ukrywanie. Ukrywa metodę klasy pochodnej. Dokonuje się tego za pomocą słowa kluczowego „nowe”.
Słowo kluczowe Override służy do zapewnienia zupełnie nowej implementacji metody klasy bazowej (oznaczonej jako „Virtual”) w klasie pochodnej.
Zasadniczo, jeśli masz coś takiego jak poniżej,
Class A
{
}
Class B:A
{
}
A a = new B();
Każda metoda wywoływana na obiekcie „a” zostanie wykonana na typie „a” (tutaj typem jest „A”). Jeśli jednak zaimplementujesz tę samą metodę w klasie B, która jest już obecna w klasie A, kompilator ostrzega przed użyciem słowa kluczowego „Nowe”. Jeśli użyjesz „Nowy”, ostrzeżenie zniknie. Poza tym nie ma różnicy między używaniem „New” a nieużywaniem go w odziedziczonej klasie.
W niektórych sytuacjach może zajść potrzeba wywołania metody klasy referencyjnej, którą w danym momencie posiada dana instancja, zamiast wywoływania metody typu obiektowego. W powyższym przypadku odniesieniem, które posiada, jest „B”, ale typem jest „A”. Więc jeśli chcesz, aby wywołanie metody miało miejsce na `` B '', użyj Virtual i override, aby to osiągnąć.
Mam nadzieję że to pomoże...
Daniel Sandeep.
Jeśli jest przypadek, w którym nie możesz zmienić zawartości klasy, powiedzmy A, ale chcesz użyć jej niektórych metod, a masz metodę, której nazwa jest wspólna, możesz użyć własnej implementacji metody za pomocą newsłowa kluczowego.
Najważniejsze jest to, aby wykorzystać to, że zarówno odniesienie, jak i obiekt muszą być tego samego typu.
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();
}
}