2016-02-25 14 views
5

Mam proste trzy klasy:Nowe słowo kluczowe: dlaczego metoda pochodna nie jest wywoływana?

class A 
{ 
    public virtual void Write() 
    { 
     Console.Write("A"); 
    } 
} 

class B:A 
{ 
    public override void Write() 
    { 
     Console.Write("B"); 
    } 
} 

class C : B 
{ 
    public new void Write() 
    { 
     Console.Write("C"); 
    } 
} 

A ja tworzenia obiektów i nazywając ich metody:

A a = new A(); 
a.Write(); 

A b = new C(); 
b.Write(); 

C c = new C(); 
c.Write(); 

i wyjściowe będą: ABC

Co nie mogę zrozumieć dlaczego te kod produkuje B?:

A b = new C(); 
b.Write(); 

myślałem, że powinno być C. Jednak wielokrotnie testowałem i zawsze jest to B.

Rozumiem, że A b = new C() tworzy nowy typ obiektu C. Zatem wyjście powinno być C. Lub czy zachowaniem specjalnym jest wywołanie metody nadpisanej, gdy używamy go bez rzutowania?

Dlaczego tak się dzieje? Ponieważ nie używaliśmy żadnego odniesienia do klasy B.

+5

Ponieważ tak działa nowe słowo kluczowe. https://msdn.microsoft.com/en-us/library/ms173153.aspx – AndyJ

Odpowiedz

6

będzie działać, jeśli chcesz używać ((C)b).Write();

Z new hasła nie jesteś przesłanianie metody Write dla C, ale raczej tworzenie nowej metody jedynie zdefiniowane dla C Więc dla C rzeczywiście mają 2 metody o nazwie metody Write.

A c = new C(); 

c.Write();   //Output "B", you're calling the overridden method  
((C)c).Write();  //Output "C", you're calling the method defined on C 

//or 

(c as C).Write(); 

To samo dzieje się, kiedy będzie można zdefiniować jako C c:

C c = new C(); 

c.Write();   //Output "C"  
((A)c).Write();  //Output "B" 

w pierwszym przykładzie dzwonisz nową metodę zdefiniowaną na C. W drugiej linii, do której dzwonisz metodę Write z A, który jest nadpisywany przez B, stąd wyjście "B".

Edit: (niektóre bardziej wyjaśnienie)

Zmienna c jest typu A, więc to, co kompilator wie „c jest instancją”, że nie wiadomo, że to jest rzeczywiście z bardziej wyprowadzony typ. Gdy wywołasz na nim metodę Write, wywoła ona metodę zdefiniowaną na A (która jest nadpisywana przez B). Twoja klasa podstawowa A nie ma wiedzy o twojej nowej metodzie zdefiniowanej na C (to robi new, utwórz nową metodę), więc jeśli nie wyrzucisz go do C, aby kompilator wiedział o rzeczywistym, pochodnym typie c, metoda twoja klasa podstawowa zostanie wywołana.

+1

Często nazywany "ukrywaniem członka" lub "shadowingiem", używaj go oszczędnie i ostrożnie - może być dość drażniący, gdy spodziewasz się, że kod coś zrobi jeszcze. –

+0

Przepraszam za moje głupie pytanie, ale dlaczego ten kod 'A b = nowy C(); b.Write(); metoda "overriden call"? Mam na myśli, że 'A b = new C()' tworzy nowy typ obiektu 'C'. Więc wyjście powinno być "C". Lub czy zachowaniem szczególnym jest wywoływanie przesłoniętej metody, gdy używamy go bez rzutowania? – StepUp

+0

Aby uzyskać dostęp do metody, która ukrywa inną, potrzebne jest silnie wpisane odwołanie do typu, który definiuje ukrywanie, a nie odniesienia podstawowego. Ta sama zasada dotyczy również jawnie zaimplementowanych interfejsów.Zasadniczo nie jest to "właściwe" dziedziczenie, więc hierarchia dziedziczenia nie jest wymuszana w taki sam sposób, jak standardowe nadpisane wywołanie metody. –

Powiązane problemy