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.
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 ?? –
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
@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. –