2011-05-28 14 views

Odpowiedz

74

Słowo kluczowe wirtualne służy do modyfikowania metody, właściwości, indeksu lub deklaracji zdarzenia i pozwala na nadpisanie w klasie pochodnej. Na przykład ta metoda może zostać nadpisana przez dowolną klasę, która ją dziedziczy: Użyj nowego modyfikatora, aby jawnie ukryć element odziedziczony po klasie bazowej. Aby ukryć dziedziczony element, zadeklaruj go w klasie pochodnej, używając tej samej nazwy i zmodyfikuj ją za pomocą nowego modyfikatora.

Wszystko to ma związek z polimorfizmem. Kiedy wywoływana jest metoda wirtualna, rzeczywisty typ obiektu, do którego odnosi się odwołanie, jest używany do określenia, której implementacji metody użyć. Gdy metoda klasy bazowej jest nadpisywana w klasie pochodnej, używana jest wersja w klasie pochodnej, nawet jeśli kod wywołujący nie "wie", że obiekt był instancją klasy pochodnej. Na przykład:

public class Base 
{ 
    public virtual void SomeMethod() 
    { 
    } 
} 

public class Derived : Base 
{ 
    public override void SomeMethod() 
    { 
    } 
} 

... 

Base d = new Derived(); 
d.SomeMethod(); 

zakończy się na wywołaniu metody Derived.SomeMethod, która zastąpi metodę Base.SomeMethod.

Teraz, jeśli używasz słowa kluczowego nowy zamiast ręcznym, metoda w klasie pochodnej nie przesłonić metodę w klasie bazowej, to tylko go ukrywa. W tym przypadku kod tak:

public class Base 
{ 
    public virtual void SomeOtherMethod() 
    { 
    } 
} 

public class Derived : Base 
{ 
    public new void SomeOtherMethod() 
    { 
    } 
} 

... 


Base b = new Derived(); 
Derived d = new Derived(); 
b.SomeOtherMethod(); 
d.SomeOtherMethod(); 

najpierw zadzwonić Base.SomeOtherMethod, potem Derived.SomeOtherMethod. Są to skutecznie dwie całkowicie oddzielne metody, które mają tę samą nazwę, a nie pochodną, ​​która zastępuje metodę bazową.

Jeśli nie określisz żadnego nowego lub przesłania, wynik wyjściowy będzie taki sam, jak podano nowy, ale otrzymasz również ostrzeżenie kompilatora (ponieważ możesz nie wiedzieć, że ukrywasz metodę w metodzie klasy bazowej, a nawet być może chciałeś go zastąpić, a jedynie zapomniałeś podać słowo kluczowe).

Nadrzędna deklaracja właściwości może zawierać zmieniony modyfikator. Użycie tego modyfikatora uniemożliwia klasie pochodnej dalsze przesłonięcie właściwości. Aksesory zamkniętej nieruchomości są również zapieczętowane.

+0

dziękuję za wejście .. ale jedno nie przychodzi mi do głowy to .. co to jest użycie Base b = new Derived()? Czy jest to obiekt tworzenia klasy bazowej lub klasy pochodnej ?? –

+2

Klasa pochodna. Myślę, że musisz popatrzeć bardziej na polimorfizm. Oto dobry do czytania. http://msdn.microsoft.com/en-us/library/ms173152 (v = vs.80) .aspx – CharithJ

+3

@Xor: W takim przypadku tworzysz instancję obiektu 'Derived' i przechowujesz odwołanie w zmiennej' Base'. Jest to poprawne, ponieważ obiekt 'Derived' jest również obiektem' Base'. To tak, jakby powiedzieć, że potrzebujemy "osoby", więc dostajemy "Johnny'ego", który jest osobą. Ta sama oferta tutaj. –

15

Domyślnie metoda nie może zostać nadpisana w klasie pochodnej, chyba że zostanie zadeklarowana jako virtual lub abstract. virtual oznacza sprawdzanie nowszych implementacji przed wywołaniem i abstract oznacza to samo, ale ma pewność, że zostanie zastąpione we wszystkich klasach pochodnych. Ponadto nie jest wymagana żadna implementacja w klasie bazowej, ponieważ zostanie ona ponownie zdefiniowana w innym miejscu.

Wyjątkiem od powyższego jest modyfikator new. Metoda, która nie została zadeklarowana jako virtual lub abstract, może zostać ponownie zdefiniowana za pomocą modyfikatora new w klasie pochodnej. Po wywołaniu metody w klasie bazowej wykonywana jest metoda podstawowa, a po wywołaniu w klasie pochodnej wykonywana jest nowa metoda.Wszystkie słowa kluczowe new pozwala na to, aby mieć dwie metody o tej samej nazwie w hierarchii klas.

Wreszcie modyfikator sealed przerywa łańcuch metod virtual i sprawia, że ​​nie można ich ponownie zmienić. Nie jest to często używane, ale istnieje opcja. To sprawia, że ​​więcej sensu z łańcuchem 3 klasy każdy wynikającego z poprzedniego

A -> B -> C 

jeśli A ma virtual lub abstract metodę, czyli overridden w B, to może również zapobiec C zmienianie go ponownie deklarując to sealed w B.

sealed jest również używany w classes, i to jest, gdzie często spotykasz tego słowa kluczowego.

Mam nadzieję, że to pomoże.

29

Każda metoda może być przerabiana (= virtual) lub nie. Decyzja jest podejmowana przez który definiuje metodę:

class Person 
{ 
    // this one is not overridable (not virtual) 
    public String GetPersonType() 
    { 
     return "person"; 
    } 

    // this one is overridable (virtual) 
    public virtual String GetName() 
    { 
     return "generic name"; 
    } 
} 

Teraz możesz zastąpić te metody, które są przeciążać:

class Friend : Person 
{ 
    public Friend() : this("generic name") { } 

    public Friend(String name) 
    { 
     this._name = name; 
    } 

    // override Person.GetName: 
    public override String GetName() 
    { 
     return _name; 
    } 
} 

Ale nie można zastąpić metodę GetPersonType ponieważ nie jest wirtualny.

Stwórzmy dwie instancje tych klas:

Person person = new Person(); 
Friend friend = new Friend("Onotole"); 

Gdy metoda nie-wirtualny GetPersonType jest wywoływana przez Fiend przykład to faktycznie Person.GetPersonType że nazywa się:

Console.WriteLine(friend.GetPersonType()); // "person" 

Kiedy metoda wirtualna GetName nazywa przez Friend instancję to Friend.GetName, która nazywa się:

Console.WriteLine(friend.GetName()); // "Onotole" 

Kiedy metoda wirtualna GetName jest wywoływana przez Person przykład To Person.GetName że nazywa się:

Console.WriteLine(person.GetName()); // "generic name" 

Gdy metoda nie-wirtualny nazywa ciało metoda nie spojrzał - kompilator już zna rzeczywistą metodę, która potrzebuje być nazywanym. Podczas gdy w przypadku metod wirtualnych kompilator nie może być pewny, do kogo należy wywoływać i jest sprawdzany w środowisku wykonawczym w hierarchii klas od dołu do góry, począwszy od typu instancji, do której metoda jest wywoływana: dla friend.GetName zaczyna się od Friend klasa i znajduje ją od razu, dla klasy person.GetName zaczyna od Person i znajduje ją tam.

Czasem trzeba zrobić podklasę, przesłonić metodę wirtualną i nie chcesz już więcej przesłonięcia w dół w hierarchii - użyć sealed override za to (mówiąc jesteś ostatnią osobą, która zastępuje metodę):

class Mike : Friend 
{ 
    public sealed override String GetName() 
    { 
     return "Mike"; 
    } 
} 

Ale czasami twój przyjaciel Mike postanawia zmienić swoją płeć, a zatem jego imię Alice :) można albo zmienić oryginalny kod lub zamiast podklasy Mike:

class Alice : Mike 
{ 
    public new String GetName() 
    { 
     return "Alice"; 
    } 
} 

Tutaj można tworzyć zupełnie inną metodę o tej samej nazwie (teraz ty mają dwa). Która metoda i kiedy jest wywoływana? To zależy od tego, jak to nazwać:

Alice alice = new Alice(); 
Console.WriteLine(alice.GetName());    // the new method is called, printing "Alice" 
Console.WriteLine(((Mike)alice).GetName());  // the method hidden by new is called, printing "Mike" 

Kiedy zadzwonić z Alice „perspektywy s zadzwonić Alice.GetName, gdy z Mike” s - zadzwonić Mike.GetName. W tym przypadku nie jest wykonywane wyszukiwanie w czasie wykonywania, ponieważ obie metody są nie-wirtualne.

Zawsze można utworzyć metody new - niezależnie od tego, czy ukrywane metody są wirtualne, czy nie.

Dotyczy to również właściwości i zdarzeń - są one reprezentowane jako metody pod spodem.

+0

Nie ma prostej i kompletnej odpowiedzi, niż to gdziekolwiek znalazłem. Dzięki Loki – Reevs

5
public class Base 
{ 
    public virtual void SomeMethod() 
    { 
    Console.WriteLine("B"); 
    } 
    } 

    //This one is Simple method 
public class Derived : Base 
{ 
    public void SomeMethod() 
    { 
    Console.WriteLine("D"); 
    } 

    //This method has 'new' keyword 
    public new void SomeMethod() 
    { 
    Console.WriteLine("D"); 
    } 

    //This method has 'override' keyword 
    public override void SomeMethod() 
    { 
    Console.WriteLine("D"); 
    } 
} 

Teraz Pierwszą rzeczą pierwsze

Base b=new Base(); 
Derived d=new Derived(); 
b.SomeMethod(); will always write B 
d.SomeMethod(); will always write D 

Teraz wyszukiwane są o polimorfizmu

       Base b = new Derived(); 
  1. Korzystanie virtual w klasie bazowej i zastępują w Derived da D (polimorfizm).
  2. Korzystanie zw spowoduje błąd.
  3. Podobnie napisanie metody (bez przesłonięcia) z virtual spowoduje napisanie "B" z ostrzeżeniem (ponieważ nie jest wykonywany polimorfizm).
  4. Aby ukryć takie ostrzeżenie jak w powyższym punkcie, napisz new przed tą prostą metodą w Derived.
  5. new Słowo kluczowe to kolejna historia, po prostu ukrywa ostrzeżenie informujące, że właściwość o tej samej nazwie występuje w klasie bazowej.
  6. virtual lub new oba są takie same z wyjątkiem new modifier

  7. new i override nie może być stosowany przed samą metodą lub mienia.

  8. sealed zanim jakakolwiek klasa lub metoda zablokuje ją do użycia w klasie pochodnej i spowoduje błąd czasu kompilacji.
+0

Niestety, ale -1 z powodu wielu błędów kompilacji: metoda zadeklarowana wiele razy z tymi samymi parametrami, bez cudzysłowów wokół ciągów B & D ... – DeveloperDan

Powiązane problemy