Jaka jest różnica między funkcją abstrakcyjną a funkcją wirtualną? W jakich przypadkach zaleca się stosowanie wirtualnych lub abstrakcyjnych? Które z nich jest najlepsze?
oop
programming-languages
abstract
virtual-functions
Moran Helman
źródło
źródło
Odpowiedzi:
Funkcja abstrakcyjna nie może mieć funkcji. Mówisz w zasadzie, że każda klasa potomna MUSI podać własną wersję tej metody, jednak zbyt ogólna jest nawet próba implementacji w klasie nadrzędnej.
Funkcja wirtualna to po prostu wygląd, oto funkcjonalność, która może, ale nie musi być wystarczająca dla klasy potomnej. Więc jeśli jest wystarczająco dobry, skorzystaj z tej metody, jeśli nie, zastąp mnie i zapewnij własną funkcjonalność.
źródło
Funkcja abstrakcyjna nie ma implementacji i można ją zadeklarować tylko w klasie abstrakcyjnej. Zmusza to klasę pochodną do zapewnienia implementacji.
Funkcja wirtualna zapewnia domyślną implementację i może istnieć w klasie abstrakcyjnej lub nieabstrakcyjnej.
Na przykład:
źródło
MyBase
klasa nie musi w jakiś sposób implementować klasy abstrakcyjnej ? Nie robię tego często, więc mogę się mylić. Nie widzę tego w twoim przykładzie.abstract
klasy mogą miećabstract
członków.abstract
Klasa niebędąca dziedziczeniem poabstract
klasie musi miećoverride
swoichabstract
członków.abstract
Członkiem jest niejawnievirtual
.abstract
Członek nie może zapewnić realizacji (abstract
nazywany jestpure virtual
w niektórych językach).źródło
virtual
lub nievirtual
. Elementabstract
członkowski (tj. Właściwość abstrakcyjna, metoda abstrakcyjna) jest podobny do metody wirtualnej, tzn. Można ją przesłonić, z tą różnicą, że nie ma ona domyślnej implementacji.Zawsze musisz zastąpić funkcję abstrakcyjną.
A zatem:
źródło
Funkcja abstrakcyjna:
Funkcja wirtualna:
źródło
Metoda abstrakcyjna: jeśli klasa zawiera metodę abstrakcyjną, należy ją zadeklarować jako abstrakcyjną. Metoda abstrakcyjna nie ma implementacji, a zatem klasy wywodzące się z tej klasy abstrakcyjnej muszą zapewniać implementację tej metody abstrakcyjnej.
Metoda wirtualna: klasa może mieć metodę wirtualną. Metoda wirtualna ma implementację. Kiedy dziedziczą z klasy, która ma metodę wirtualną, to można zastąpić metodę wirtualną i zapewnić dodatkową logikę, lub wymienić logikę z własnej realizacji.
Kiedy stosować: W niektórych przypadkach wiesz, że niektóre typy powinny mieć określoną metodę, ale nie wiesz, jaką implementację powinna mieć ta metoda.
W takich przypadkach można utworzyć interfejs zawierający metodę z tym podpisem. Jeśli jednak masz taki przypadek, ale wiesz, że implementatorzy tego interfejsu będą mieli także inną wspólną metodę (dla której możesz już zapewnić implementację), możesz utworzyć klasę abstrakcyjną. Ta klasa abstrakcyjna zawiera następnie metodę abstrakcyjną (którą należy zastąpić) i inną metodę, która zawiera logikę „wspólną”.
Metodę wirtualną należy zastosować, jeśli masz klasę, której można użyć bezpośrednio, ale dla której chcesz, aby spadkobiercy mogli zmieniać określone zachowanie, chociaż nie jest to obowiązkowe.
źródło
wyjaśnienie: z analogiami. mam nadzieję, że ci to pomoże.
Kontekst
Pracuję na 21 piętrze budynku. I jestem paranoikiem ognia. Co jakiś czas, gdzieś na świecie, ogień spala skrobak do nieba. Ale na szczęście mamy gdzieś tutaj instrukcję dotyczącą postępowania w przypadku pożaru:
Wyjście pożarowe()
Jest to w zasadzie wirtualna metoda o nazwie FireEscape ()
Metoda wirtualna
Ten plan jest całkiem dobry na 99% okoliczności. To podstawowy plan, który działa. Ale istnieje 1% szansy na zablokowanie lub uszkodzenie wyjścia ewakuacyjnego, w którym to przypadku jesteś całkowicie wkręcony i staniesz się toastem, chyba że podejmiesz drastyczne działania. Za pomocą metod wirtualnych możesz to zrobić: możesz zastąpić podstawowy plan FireEscape () własną wersją planu:
Innymi słowy, metody wirtualne zapewniają podstawowy plan, który można zastąpić w razie potrzeby . Podklasy mogą przesłonić metodę wirtualną klasy nadrzędnej, jeśli programista uzna to za stosowne.
Metody abstrakcyjne
Nie wszystkie organizacje są dobrze wywiercone. Niektóre organizacje nie przeprowadzają ćwiczeń przeciwpożarowych. Nie mają ogólnej polityki ucieczki. Każdy człowiek jest dla siebie. Zarząd jest zainteresowany tylko taką polityką.
Innymi słowy, każda osoba jest zmuszona opracować własną metodę FireEscape (). Jeden facet wyjdzie z wyjścia ewakuacyjnego. Kolejny facet spadnie ze spadochronem. Inny facet użyje technologii napędu rakietowego, aby odlecieć z budynku. Kolejny facet zejdzie na ląd. Kierownictwo nie dba o to, jak uciekniesz, o ile masz podstawowy plan FireEscape () - jeśli nie, możesz mieć gwarancję, że BHP spadnie na organizację jak tona cegieł. To właśnie należy rozumieć metodą abstrakcyjną.
Jaka jest różnica między nimi ponownie?
Metoda abstrakcyjna: podklasy są zmuszone do implementacji własnej metody FireEscape. Dzięki metodzie wirtualnej czeka na Ciebie podstawowy plan, ale możesz go wdrożyć, jeśli nie jest wystarczająco dobry.
To nie było takie trudne, prawda?
źródło
Metoda abstrakcyjna to metoda, którą należy zaimplementować, aby stworzyć konkretną klasę. Deklaracja należy do klasy abstrakcyjnej (a każda klasa z metodą abstrakcyjną musi być klasą abstrakcyjną) i musi być zaimplementowana w konkretnej klasie.
Metoda wirtualna to metoda, którą można przesłonić w klasie pochodnej za pomocą przesłonięcia, zastępując zachowanie w nadklasie. Jeśli nie przesłonisz, uzyskasz oryginalne zachowanie. Jeśli to zrobisz, zawsze otrzymasz nowe zachowanie. W przeciwieństwie do metod nie wirtualnych, których nie można zastąpić, ale można ukryć oryginalną metodę. Odbywa się to za pomocą
new
modyfikatora.Zobacz następujący przykład:
Kiedy tworzę instancję
DerivedClass
i dzwonięSayHello
, alboSayGoodbye
dostaję „Cześć” i „Do zobaczenia później”. Jeśli zadzwonięHelloGoodbye
, dostanę „Cześć” i „Do zobaczenia później”. Jest tak, ponieważSayGoodbye
jest wirtualny i można go zastąpić klasami pochodnymi.SayHello
jest tylko ukryty, więc kiedy wywołuję to z mojej klasy podstawowej, otrzymuję moją oryginalną metodę.Metody abstrakcyjne są domyślnie wirtualne. Definiują zachowanie, które musi być obecne, podobnie jak interfejs.
źródło
Metody abstrakcyjne są zawsze wirtualne. Nie mogą mieć implementacji.
To główna różnica.
Zasadniczo użyłbyś wirtualnej metody, jeśli masz jej „domyślną” implementację i chcesz pozwolić potomnym na zmianę jej zachowania.
Metodą abstrakcyjną zmuszasz potomków do zapewnienia implementacji.
źródło
Uprościłem to, wprowadzając ulepszenia w następujących klasach (z innych odpowiedzi):
źródło
Wiązanie to proces mapowania nazwy na jednostkę kodu.
Późne wiązanie oznacza, że używamy nazwy, ale odraczamy mapowanie. Innymi słowy, najpierw tworzymy / wspominamy nazwę i pozwalamy, aby jakiś późniejszy proces obsługiwał mapowanie kodu na tę nazwę.
Teraz rozważ:
Tak więc krótka odpowiedź brzmi:
virtual
jest późną instrukcją wiązania dla maszyny (środowiska wykonawczego), podczas gdyabstract
jest późną instrukcją wiązania dla człowieka (programisty)Innymi słowy
virtual
oznacza:„Drogi środowisku wykonawczym , powiąż odpowiedni kod z tą nazwą, robiąc to, co robisz najlepiej: wyszukiwanie ”
abstract
Oznacza natomiast :„Drogi programatorze , powiąż odpowiedni kod z tą nazwą, robiąc to, co robisz najlepiej: wymyślając ”
Dla zachowania kompletności przeciążenie oznacza:
„Drogi kompilatorze , powiąż odpowiedni kod z tą nazwą, robiąc to, co robisz najlepiej: sortowanie ”.
źródło
Zasadniczo używasz metody wirtualnej, gdy chcesz, aby spadkobiercy rozszerzyli funkcjonalność, JEŚLI chcą.
Stosujesz metody abstrakcyjne, gdy chcesz, aby spadkobiercy wdrożyli tę funkcję (w tym przypadku nie mają wyboru)
źródło
Metoda wirtualna :
Wirtualny oznacza, że MOŻEMY to zastąpić.
Funkcja wirtualna ma implementację. Gdy odziedziczymy klasę, możemy zastąpić funkcję wirtualną i podać własną logikę.
funkcji w klasie potomnej (co można powiedzieć jako pojęcie
Shadowing).
Metoda abstrakcyjna
Abstrakt oznacza, że MUSIMY go zastąpić.
Funkcja abstrakcyjna nie ma implementacji i musi należeć do klasy abstrakcyjnej.
Można to tylko zadeklarować. Zmusza to klasę pochodną do zapewnienia jej implementacji.
Członek abstrakcyjny jest domyślnie wirtualny. Abstrakt można nazwać czystym wirtualnym w niektórych językach.
źródło
Widziałem w niektórych miejscach metodę abstrakcyjną zdefiniowaną jak poniżej. **
** Czułem, że to jest.
Nie jest konieczne, aby metoda abstrakcyjna musiała zostać zaimplementowana w klasie potomnej, jeśli klasa potomna jest również abstrakcyjna .
1) Metoda abstrakcyjna nie może być metodą prywatną. 2) Metoda abstrakcyjna nie może być zaimplementowana w tej samej klasie abstrakcyjnej.
Powiedziałbym ... jeśli wdrażamy klasę abstrakcyjną, musisz zastąpić metody abstrakcyjne z podstawowej klasy abstrakcyjnej. Ponieważ .. Implementacja metody abstrakcyjnej polega na zastąpieniu słowa kluczowego. Podobna do metody wirtualnej.
Metoda wirtualna nie musi być implementowana w odziedziczonej klasie.
źródło
Większość powyższych przykładów używa kodu - i są one bardzo, bardzo dobre. Nie muszę dodawać do tego, co mówią, ale poniżej znajduje się proste objaśnienie, które wykorzystuje analogie, a nie kod / terminy techniczne.
Proste objaśnienie - objaśnienie za pomocą analogii
Metoda abstrakcyjna
Pomyśl George W. Bush. Mówi do swoich żołnierzy: „Idź walczyć w Iraku”. I to wszystko. Wszystko, co określił, to konieczność walki. Nie określa, jak dokładnie to się stanie. Ale nie można po prostu wyjść i „walczyć”: co to dokładnie znaczy? czy walczę z B-52 czy z moim derringerem? Te szczegółowe informacje pozostawia się komuś innemu. To jest metoda abstrakcyjna.
Metoda wirtualna
David Petraeus jest wysoko w wojsku. Zdefiniował, co oznacza walka:
Problem polega na tym, że jest to bardzo ogólna metoda. To dobra metoda, która działa, ale czasami nie jest wystarczająco szczegółowa. Dobrą rzeczą dla Petraeusa jest to, że jego rozkazy mają swobodę działania i zakres - pozwolił innym zmienić jego definicję „walki”, zgodnie z ich szczególnymi wymaganiami.
Prywatna praca Bloggs czyta zamówienie Petraeusa i otrzymuje pozwolenie na wdrożenie własnej wersji walki, zgodnie z jego szczególnymi wymaganiami:
Nouri al Maliki również otrzymuje te same zamówienia od Petraeusa. On też ma walczyć. Ale jest politykiem, a nie piechotą. Oczywiście nie może chodzić i strzelać w głowę swoim politycznym wrogom. Ponieważ Petraeus dał mu wirtualną metodę, Maliki może wdrożyć własną wersję metody walki, w zależności od jego szczególnych okoliczności:
Innymi słowy, metoda wirtualna dostarcza instrukcji na tablicy - ale są to instrukcje ogólne, które mogą być bardziej szczegółowe dla osób z dziedzicznej armii, w zależności od ich szczególnych okoliczności.
Różnica między nimi
George Bush nie potwierdza żadnych szczegółów implementacyjnych. Musi to zapewnić ktoś inny. To jest metoda abstrakcyjna.
Petraeus z drugiej strony ma podać szczegóły implementacji, ale dał pozwolenie na swoich podwładnych, aby zastąpić jego rozkazy z własnej wersji, czy mogą wymyślić coś lepszego.
mam nadzieję, że to pomaga.
źródło
Funkcja abstrakcyjna (metoda):
● Metoda abstrakcyjna to metoda zadeklarowana za pomocą słowa kluczowego streszczenie.
● Nie ma ciała.
● Powinien zostać zaimplementowany przez klasę pochodną.
● Jeśli metoda jest abstrakcyjna, klasa powinna abstrakować.
funkcja wirtualna (metoda):
● Metoda wirtualna to metoda zadeklarowana za pomocą słowa kluczowego virtual i może być zastąpiona przez metodę klasy pochodnej za pomocą słowa kluczowego override.
● Od klasy pochodnej zależy, czy ją zastąpić, czy nie.
źródło
Odpowiedź była udzielana wiele razy, ale pytanie o to, kiedy użyć każdej z nich, jest decyzją w czasie projektowania. Uważam, że dobrą praktyką jest łączenie wspólnych definicji metod w odrębne interfejsy i wciąganie ich do klas na odpowiednich poziomach abstrakcji. Zrzucenie wspólnego zestawu abstrakcyjnych i wirtualnych definicji metod do klasy sprawia, że klasa staje się niemożliwa do ustalenia, kiedy najlepiej zdefiniować nieabstrakcyjną klasę, która implementuje zestaw zwięzłych interfejsów. Jak zawsze zależy to od tego, co najlepiej odpowiada konkretnym potrzebom aplikacji.
źródło
Funkcja abstrakcyjna nie może mieć ciała i MUSI być nadpisana przez klasy potomne
Funkcja wirtualna będzie miała ciało i może zostać zastąpiona przez klasy potomne
źródło
Z ogólnego widoku obiektowego:
Odnośnie metody abstrakcyjnej : Kiedy umieścisz metodę abstrakcyjną w klasie nadrzędnej, tak naprawdę mówisz do klas podrzędnych: Hej, zauważ, że masz taką sygnaturę metody. A jeśli chcesz go użyć, powinieneś wdrożyć własne!
Odnośnie funkcji wirtualnej : Kiedy umieścisz metodę wirtualną w klasie nadrzędnej, mówisz do klas pochodnych: Hej, jest tu funkcjonalność, która coś dla ciebie robi. Jeśli jest to przydatne, po prostu go użyj. Jeśli nie, zastąp to i zaimplementuj swój kod, nawet ty możesz użyć mojej implementacji w swoim kodzie!
to jest jakaś filozofia na temat różnic pomiędzy tą dwiema koncepcjami w Generalnym OO
źródło
Funkcja abstrakcyjna to „tylko” podpis, bez implementacji. Jest on używany w interfejsie, aby zadeklarować sposób użycia klasy. Musi być zaimplementowany w jednej z pochodnych klas.
Funkcja wirtualna (właściwie metoda) jest również funkcją, którą deklarujesz i powinna zostać zaimplementowana w jednej z klas hierarchii dziedziczenia.
Dziedziczone wystąpienia takiej klasy również dziedziczą implementację, chyba że ją zaimplementujesz, w niższej klasie hierarchicznej.
źródło
Jeśli klasa wywodzi się z tej klasy abstrakcyjnej, jest wówczas zmuszana do zastąpienia elementu abstrakcyjnego. Różni się to od wirtualnego modyfikatora, który określa, że element może być opcjonalnie zastąpiony.
źródło
W języku C # nie ma żadnych wywołań klas wirtualnych.
Dla funkcji
Możesz zdecydować na podstawie swoich wymagań.
źródło
Metoda abstrakcyjna nie ma implementacji, jest zadeklarowana w klasie nadrzędnej. Klasa potomna odpowiada za implementację tej metody.
Metoda wirtualna powinna mieć implementację w klasie nadrzędnej i ułatwia klasie podrzędnej dokonanie wyboru, czy użyć tej implementacji klasy nadrzędnej, czy mieć nową implementację dla tej metody w klasie podrzędnej.
źródło
Z tła C ++, C # virtual odpowiada C ++ virtual, podczas gdy metody abstrakcyjne C # odpowiadają funkcji C ++ pure virtual
źródło
Abstrakcyjna funkcja lub metoda jest publiczną „nazwą operacji” ujawnioną przez klasę, jej cel, wraz z klasami abstrakcyjnymi, stanowi przede wszystkim formę ograniczenia w projektowaniu obiektów w stosunku do struktury, którą obiekt musi zaimplementować.
W rzeczywistości klasy, które dziedziczą po klasie abstrakcyjnej, muszą podać implementację tej metody, generalnie kompilatory zgłaszają błędy, gdy tego nie robią.
Korzystanie z klas i metod abstrakcyjnych jest ważne przede wszystkim, aby tego uniknąć, ponieważ koncentrując się na szczegółach implementacji podczas projektowania klas, struktura klas jest zbyt powiązana z implementacjami, tworząc w ten sposób zależności i łącząc klasy, które ze sobą współpracują.
Wirtualna funkcja lub metoda jest po prostu metodą modelującą publiczne zachowanie klasy, ale możemy ją dowolnie modyfikować w łańcuchu dziedziczenia, ponieważ uważamy, że klasy potomne mogą wymagać zaimplementowania określonych rozszerzeń dla tego zachowania.
Obie reprezentują formę polimorfizmu w paradygmacie orientacji obiektowej.
Możemy używać razem metod abstrakcyjnych i funkcji wirtualnych do obsługi dobrego modelu dziedziczenia.
Projektujemy dobrą abstrakcyjną strukturę głównych obiektów naszego rozwiązania, następnie tworzymy podstawowe implementacje, lokalizując te bardziej podatne na dalsze specjalizacje i wykonujemy je jako wirtualne, w końcu specjalizujemy się w naszych podstawowych implementacjach, ostatecznie „zastępując” odziedziczone wirtualne.
źródło
Piszę tutaj przykładowy kod z nadzieją, że może to być namacalny przykład, aby zobaczyć zachowania interfejsów, klas abstrakcyjnych i zwykłych klas na bardzo podstawowym poziomie. Możesz również znaleźć ten kod w github jako projekt, jeśli chcesz go użyć jako wersji demonstracyjnej: https://github.com/usavas/JavaAbstractAndInterfaceDemo
źródło
W moim rozumieniu:
Metody abstrakcyjne:
Tylko klasa abstrakcyjna może przechowywać metody abstrakcyjne. Również klasa pochodna musi zaimplementować metodę, a klasa nie zapewnia żadnej implementacji.
Metody wirtualne:
Klasa może je zadeklarować, a także zapewnić ich implementację. Również klasa pochodna musi zaimplementować metodę, aby ją zastąpić.
źródło