2012-07-06 21 views
6

to jest mały kod, który pokazuje wirtualne metody.Potrzebujesz zrozumieć poniższy kod dla wirtualnych metod C#

class A 
{ 
    public virtual void F() { Console.WriteLine("A.F"); } 
} 
class B: A 
{ 
    public override void F() { Console.WriteLine("B.F"); } 
} 
class C: B 
{ 
    new public virtual void F() { Console.WriteLine("C.F"); } 
} 
class D: C 
{ 
    public override void F() { Console.WriteLine("D.F"); } 
} 

class Test 
{ 
    static void Main() 
    { 
    D d = new D(); 
    A a = d; 
    B b = d;   

    a.F(); 
    b.F();   
} 
} 

Ten kod drukuje poniższy wynik:

B.F 
B.F 

Nie mogę zrozumieć, dlaczego a.F() drukuje B.F?

Myślałem, że wydrukuje DF, ponieważ klasa B zastępuje F() klasy A, wówczas ta metoda jest ukrywana w klasie C za pomocą słowa kluczowego "nowy", to znowu jest nadpisywana w klasie D. Tak więc w końcu DF gorset.

ale tego nie robi. Czy mógłbyś wyjaśnić, dlaczego drukuje B.F?

Odpowiedz

5
A a = d; 
a.F(); 

Znajdzie się F() w następujący sposób.

  1. pierwsze w class A
  2. Następnie w class B
  3. Następnie w class C
  4. Następnie w class D

Teraz F() będzie można znaleźć w A i B. W ten sposób zostanie wywołany B.F(). In class C F() jest inny (ponieważ jest to nowa implementacja i nie zastępuje z A/B). W trzecim kroku nie można znaleźć c.F(). W klasie D nadpisuje nową funkcję stworzoną przez C, a zatem nie zostanie znaleziony.

Z powodu nowego hasła, otrzymany kod jest jak następuje (w odniesieniu do wirtualnego override)

class A 
    { 
     public virtual void F() { Console.WriteLine("A.F"); } 
    } 
    class B: A 
    { 
     public override void F() { Console.WriteLine("B.F"); } 
    } 
    class C: B 
    { 
     public virtual void F1() { Console.WriteLine("C.F"); } 
    } 
    class D: C 
    { 
     public override void F1() { Console.WriteLine("D.F"); } 
    } 
+0

Dziękuję Tilak i wszystkim, mam to teraz :-) –

2

W przeciwieństwie do metody przesłonięcia, która pozwala na polimorfizm, ukrywanie metody za pomocą słowa kluczowego new jest tylko kwestią nazewnictwa (i pamiętaj, że użycie new powoduje po prostu usunięcie ostrzeżenia, że ​​coś ukrywasz).

W klasie C, gdy zadeklarujesz:

new public virtual void F() { ... } 

Tutaj jesteś definiując nowy sposób niezwiązanych z nadklasą na F(), co zdarza się mieć taką samą nazwę.

Instancja F jest przypisany zmiennej typu A lub B, wywołanie F() pomocą tych punktów zmienne sposobu zdefiniowanego przez nadrzędnej.

Wyobraź sobie, że nie zadzwoniłeś pod numer C, ale coś innego, jak G(). Poniższy kod nie kompilacji:

a.G(); 
b.G(); 

Ponieważ ze zmiennymi statycznie typowanych jako A lub B, kompilator nie widzi nowo zadeklarowanej metody. Ta sama sytuacja występuje w twoim przykładzie, z tą różnicą, że nadklasa ma oryginalną metodę o nazwie F() do wywoływania.

1

A.F zostaje nadpisany przez B.F Dlatego, gdy zostanie wywołane A.F, wykona B.F. B.F jest "podłączony" do "A.F".

Teraz C.F ukrywa B.F z nowym słowem kluczowym. C.F nie jest podłączony do B.F/A.F. Kiedy utworzysz C i wywołasz F(), wykonasz C.F. Jeśli rzutujesz C na A lub B i wywołujesz F, wykonasz B.F, ponieważ B.F i A.F są połączone.

C.F jest nadpisany przez D.F. Są połączone. Po wywołaniu C.F lub D.F wykona funkcję D.F. Teraz, gdy rzucisz obiekt D na A lub B i zadzwonisz do F(), zadzwoni B.F.

Mam nadzieję, że to pomoże ci to wyjaśnić.

Powiązane problemy