Zastanawiasz się, jaka jest różnica między następującymi:
Przypadek 1: klasa podstawowa
public void DoIt();
Przypadek 1: Dziedziczona klasa
public new void DoIt();
Przypadek 2: klasa podstawowa
public virtual void DoIt();
Przypadek 2: Dziedziczona klasa
public override void DoIt();
Zarówno przypadek 1, jak i 2 wydają się mieć ten sam efekt na podstawie testów, które przeprowadziłem. Czy jest jakaś różnica lub preferowany sposób?
c#
inheritance
overriding
new-operator
Shiraz Bhaiji
źródło
źródło
Odpowiedzi:
zadzwoni,
Derived.DoIt
jeśli to zastąpiBase.DoIt
.Najpierw zadzwonić
Base.DoIt
, wtedyDerived.DoIt
. W rzeczywistości są to dwie całkowicie odrębne metody, które mają tę samą nazwę, a nie metoda pochodna zastępująca metodę podstawową.Źródło: blog Microsoft
źródło
This indicates for the compiler to use the last defined implementation of a method
. jak znaleźć ostatnią zdefiniowaną implementację metody?override
metodę tylko wtedy, gdy klasa podstawowa zdefiniuje metodę jakovirtual
. Słowovirtual
jest klasą bazową mówiąc: „Hej, kiedy wywołanie tej metody, to mógłby praktycznie zostały zastąpione realizacji pochodnej, więc naprawdę nie wiem z góry, jaka metoda realizacja ja faktycznie dzwoni w czasie wykonywania. Więcvirtual
oznacza to symbol zastępczy metody. Oznacza to, że metod, które nie są oznaczone jakovirtual
nie można zastąpić, ale można zastąpić dowolną nie-wirtualną metodę w klasie pochodnej modyfikatoremnew
, dostępnym tylko na poziomie pochodnym.virtual : wskazuje, że dziedziczenie może zastąpić metodę
override : zastępuje funkcjonalność metody wirtualnej w klasie bazowej, zapewniając inną funkcjonalność.
nowość : ukrywa oryginalną metodę (która nie musi być wirtualna), zapewniając inną funkcjonalność. Należy tego używać tylko wtedy, gdy jest to absolutnie konieczne.
Po ukryciu metody nadal można uzyskać dostęp do oryginalnej metody, rzutując w górę na klasę podstawową. Jest to przydatne w niektórych scenariuszach, ale niebezpieczne.
źródło
override
i / lubnew
bezvirtual
niej?W pierwszym przypadku ukrywasz definicję w klasie nadrzędnej. Oznacza to, że zostanie on wywołany tylko wtedy, gdy będziesz miał do czynienia z obiektem jako klasą potomną. Jeśli rzutujesz klasę na jej typ nadrzędny, metoda rodzica zostanie wywołana. W drugim przypadku metoda jest nadpisywana i będzie wywoływana niezależnie od tego, czy obiekt jest rzutowany jako klasa potomna czy nadrzędna.
źródło
spróbuj wykonać następujące czynności: (case1)
Edycja: wirtualny + przesłonięcie jest rozwiązywane w czasie wykonywania (więc przesłonięcie naprawdę zastępuje metody wirtualne), podczas gdy nowy po prostu utwórz nową metodę o tej samej nazwie i ukrywa stary, jest on rozwiązywany w czasie kompilacji -> Twój kompilator wywoła metodę „ widzi „
źródło
W przypadku 1, jeśli użyłeś metody DoIt () odziedziczonej klasy, podczas gdy typ jest zadeklarowany jako klasa podstawowa, zobaczysz nawet akcję klasy podstawowej.
źródło
Różnica między tymi dwoma przypadkami polega na tym, że w przypadku 1
DoIt
metoda podstawowa nie jest zastępowana, tylko ukryta. Oznacza to, że w zależności od typu zmiennej zależy, która metoda zostanie wywołana. Na przykład:Może to być bardzo mylące i skutkuje nieoczekiwanym zachowaniem, którego należy unikać, jeśli to możliwe. Tak więc preferowanym sposobem byłby przypadek 2.
źródło
Chciałbym pamiętać, że oba słowa kluczowe są sobie przeciwne.
override
:virtual
należy zdefiniować słowo kluczowe, aby zastąpić metodę. Metoda wykorzystującaoverride
słowo kluczowe, które niezależnie od typu odwołania (odwołanie do klasy bazowej lub pochodnej), jeśli jest tworzone z klasą bazową, działa metoda klasy bazowej. W przeciwnym razie działa metoda klasy pochodnej.new
: jeśli słowo kluczowe jest używane przez metodę, w przeciwieństwie dooverride
słowa kluczowego, typ odniesienia jest ważny. Jeśli zostanie utworzona instancja z klasą pochodną, a typem referencyjnym jest klasa bazowa, uruchomiona zostanie metoda klasy bazowej. Jeśli zostanie utworzona instancja z klasą pochodną, a typem referencyjnym jest klasa pochodna, zostanie uruchomiona metoda klasy pochodnej. Mianowicie jest to kontrastoverride
słowa kluczowego. En passant, jeśli zapomnisz lub pominiesz dodanie nowego słowa kluczowego do metody, kompilator zachowuje się domyślnie, gdynew
używane jest słowo kluczowe.Zadzwoń w głównej części:
Wynik:
Przykład nowego kodu,
Graj kodem, komentując jeden po drugim.
źródło
Jeśli słowo kluczowe
override
jest używane w klasie pochodnej, to zastępuje metodę nadrzędną.Jeśli słowo kluczowe
new
jest używane w klasie wyprowadzającej, wyprowadza metodę ukrytą metodą nadrzędną.źródło
Miałem to samo pytanie i to jest bardzo mylące, należy wziąć pod uwagę to zastąpienie i nowe słowa kluczowe działające tylko z obiektami klasy bazowej typu i wartością klasy pochodnej. W tym przypadku tylko zobaczysz efekt ręcznego i nowy: Więc jeśli masz
class A
iB
,B
dziedziczyA
, wtedy instancję obiektu tak:Teraz przy wywoływaniu metody wezmą pod uwagę jego stan. Przesłonięcie : oznacza, że rozszerza funkcję metody, następnie używa metody w klasie pochodnej, podczas gdy nowy nakazuje kompilatorowi, aby ukrył metodę w klasie pochodnej i zamiast tego używa metody w klasie bazowej. Oto bardzo dobry widok na ten temat:
https://msdn.microsoft.com/EN-US/library/ms173153%28v=VS.140,d=hv.2%29.aspx?f=255&MSPPError=-2147217396
źródło
Poniższy artykuł znajduje się na stronie vb.net, ale myślę, że wyjaśnienie na temat zastąpienia nowego vs zastąpienia jest bardzo łatwe do zrozumienia.
https://www.codeproject.com/articles/17477/the-dark-shadow-of-overrides
W pewnym momencie tego artykułu znajduje się zdanie:
Przyjęta odpowiedź na to pytanie jest idealna, ale myślę, że ten artykuł zawiera dobre przykłady, które mogą nadać lepszy sens różnicom między tymi dwoma słowami kluczowymi.
źródło
Spośród tych wszystkich nowość jest najbardziej zagmatwana. Poprzez eksperymentowanie nowe słowo kluczowe przypomina programistom opcję zastąpienia implementacji klasy dziedziczącej implementacją klasy podstawowej poprzez jawne zdefiniowanie typu. To jest jak myślenie na odwrót.
W poniższym przykładzie wynik zwróci „Wynik pochodny”, dopóki typ nie zostanie jawnie zdefiniowany jako test BaseClass, tylko wtedy zostanie zwrócony „Wynik podstawowy”.
źródło
Różnica funkcjonalna nie zostanie pokazana w tych testach:
W tym przykładzie wywoływana jest Doit, której się spodziewasz.
Aby zobaczyć różnicę, musisz to zrobić:
Zobaczysz, jeśli uruchomisz ten test, że w przypadku 1 (tak jak go zdefiniowałeś),
DoIt()
wBaseClass
nazywa, w przypadku 2 (zgodnie z definicją), przy czymDoIt()
wDerivedClass
nazywa.źródło
W pierwszym przypadku wywoła metodę pochodnej klasy DoIt (), ponieważ nowe słowo kluczowe ukrywa metodę klasy bazowej DoIt ().
W drugim przypadku wywoła przesłoniętą funkcję DoIt ()
pozwól stworzyć instancję tych klas
Wszystko oczekuje się powyżej. Pozwól ustawić instanceB i instanceC na instanceA i wywołaj metodę DoIt () i sprawdź wynik.
źródło
Wszystkie kombinacje none, virtual, override, new i abstract:
źródło