Jaka jest różnica między funkcją abstrakcyjną a funkcją wirtualną?


1578

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?


271
Funkcja abstrakcyjna musi zostać zastąpiona, podczas gdy funkcja wirtualna może zostać zastąpiona.
Jordan Parmer

15
Funkcje wirtualne mogą mieć domyślną / ogólną implementację w klasie bazowej.
Martin

5
Kluczowym słowem jest tutaj streszczenie ; Nie istnieją i są jedynie niejasnym wyobrażeniem o tym, czym jest funkcja (podpis metody)
Cole Johnson

Odpowiedzi:


2733

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ść.


396
I oczywiście, jeśli przesłonisz metodę wirtualną, zawsze możesz odwołać się do metody nadrzędnej, wywołując base.Foo (...)
Brann

196
Dzięki. To jest znacznie lepsze i łatwiejsze wyjaśnienie niż cokolwiek w dokumentacji MSDN. (Boli mnie głowa po pięciu minutach czytania: msdn.microsoft.com/en-us/library/aa645767(v=vs.71).aspx )
Jake,

15
Pochodzę z Javy, byłem trochę zakłopotany, dlaczego w ogóle musimy zrobić to wirtualnym, dopóki nie przeczytałem: stackoverflow.com/a/1062126/193634
Rosdi Kasim

4
@MeqDotNet Oznacza to, że jeśli podoba Ci się moja implementacja, skorzystaj ze mnie, jeśli NIE napiszesz lepiej ode mnie :)
Usman Younas

16
Powinno to znajdować się w bibliotece referencyjnej Microsoft, którą spędziłem 10 minut na czytaniu i nadal jestem zdezorientowany.
SamChen

303

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:

public abstract class myBase
{
    //If you derive from this class you must implement this method. notice we have no method body here either
    public abstract void YouMustImplement();

    //If you derive from this class you can change the behavior but are not required to
    public virtual void YouCanOverride()
    { 
    }
}

public class MyBase
{
   //This will not compile because you cannot have an abstract method in a non-abstract class
    public abstract void YouMustImplement();
}

28
Bardzo przydatne, aby zobaczyć przykładowy kod - pomaga znacznie wyjaśnić różne wyjaśnienia w odpowiedziach.
Simon Tewsi

2
Cofnąłem odpowiedź do poprzedniej wersji: dwie klasy są tylko przykładami, pierwsza klasa się skompiluje, ponieważ jest oznaczona jako abstrakcyjna, druga nie. Nieważne jest, czy MyBase dziedziczy po innej klasie.
Dirk

2
Czy twoja MyBaseklasa 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.
jp2code

2
W powyższym przykładzie MyBase pokazuje, czego nie możesz zrobić. Oznacza to, że nie można mieć metody abstrakcyjnej w klasie
nieabstrakcyjnej

80
  1. Tylko abstractklasy mogą mieć abstractczłonków.
  2. abstractKlasa niebędąca dziedziczeniem po abstractklasie musi mieć override swoich abstractczłonków.
  3. abstractCzłonkiem jest niejawnie virtual.
  4. abstractCzłonek nie może zapewnić realizacji ( abstractnazywany jest pure virtualw niektórych językach).

Numer 3 nie ma dla mnie sensu. Myślę, że chciałeś powiedzieć „Członek klasy abstrakcyjnej jest domyślnie wirtualny” (tzn. Możesz zapewnić jej funkcjonalność bez konieczności określania, że ​​jest wirtualna).
Hobo Spider

5
Nie, miałem na myśli dokładnie to, co napisałem. Członek klasy abstrakcyjnej może być virtuallub nie virtual. Element abstractczł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.
Mehrdad Afshari

Cytowany „Członek abstrakcyjny jest„ domyślnie ”wirtualny”. Ale gdzieś widziałem, że ktoś stworzył członków abstrakcyjnych poprzez jawne dodanie słowa kluczowego „wirtualny”. Co nie jest konieczne i faktycznie wzbudziło we mnie wątpliwości, dopóki nie przeczytam twojej odpowiedzi.
bonCodigo

Dołącz referencje do punktu 4. Twój post nie zawiera niczego innego, czego poprzednie jeszcze nie zrobiły.
Rafael

To tylko kilka stwierdzeń bez wyjaśnień.
Reverse Engineered

61

Zawsze musisz zastąpić funkcję abstrakcyjną.

A zatem:

  • Funkcje abstrakcyjne - kiedy spadkobierca musi zapewnić własną implementację
  • Wirtualny - kiedy to do spadkobiercy należy decyzja

37

Funkcja abstrakcyjna:

  1. Można go zadeklarować tylko w klasie abstrakcyjnej.
  2. Zawiera tylko deklarację metody, a nie implementację w klasie abstrakcyjnej.
  3. Musi zostać zastąpione w klasie pochodnej.

Funkcja wirtualna:

  1. Można go zadeklarować zarówno w klasie abstrakcyjnej, jak i nieabstrakcyjnej.
  2. Zawiera implementację metody.
  3. Może zostać zastąpione.

29

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.


29

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()

  1. Nie odbieraj rzeczy
  2. Idź do ucieczki
  3. Wyjdź z budynku

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:

  1. Uruchom do okna
  2. Wyskocz przez okno
  3. Spadochron bezpiecznie na dno

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?


22

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ą newmodyfikatora.

Zobacz następujący przykład:

public class BaseClass
{
    public void SayHello()
    {
        Console.WriteLine("Hello");
    }


    public virtual void SayGoodbye()
    {
        Console.WriteLine("Goodbye");
    }

    public void HelloGoodbye()
    {
        this.SayHello();
        this.SayGoodbye();
    }
}


public class DerivedClass : BaseClass
{
    public new void SayHello()
    {
        Console.WriteLine("Hi There");
    }


    public override void SayGoodbye()
    {
        Console.WriteLine("See you later");
    }
}

Kiedy tworzę instancję DerivedClassi dzwonię SayHello, albo SayGoodbyedostaję „Cześć” i „Do zobaczenia później”. Jeśli zadzwonię HelloGoodbye, dostanę „Cześć” i „Do zobaczenia później”. Jest tak, ponieważ SayGoodbyejest wirtualny i można go zastąpić klasami pochodnymi. SayHellojest 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.


9

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.


9

Uprościłem to, wprowadzając ulepszenia w następujących klasach (z innych odpowiedzi):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestOO
{
    class Program
    {
        static void Main(string[] args)
        {
            BaseClass _base = new BaseClass();
            Console.WriteLine("Calling virtual method directly");
            _base.SayHello();
            Console.WriteLine("Calling single method directly");
            _base.SayGoodbye();

            DerivedClass _derived = new DerivedClass();
            Console.WriteLine("Calling new method from derived class");
            _derived.SayHello();
            Console.WriteLine("Calling overrided method from derived class");
            _derived.SayGoodbye();

            DerivedClass2 _derived2 = new DerivedClass2();
            Console.WriteLine("Calling new method from derived2 class");
            _derived2.SayHello();
            Console.WriteLine("Calling overrided method from derived2 class");
            _derived2.SayGoodbye();
            Console.ReadLine();
        }
    }


    public class BaseClass
    {
        public void SayHello()
        {
            Console.WriteLine("Hello\n");
        }
        public virtual void SayGoodbye()
        {
            Console.WriteLine("Goodbye\n");
        }

        public void HelloGoodbye()
        {
            this.SayHello();
            this.SayGoodbye();
        }
    }


    public abstract class AbstractClass
    {
        public void SayHello()
        {
            Console.WriteLine("Hello\n");
        }


        //public virtual void SayGoodbye()
        //{
        //    Console.WriteLine("Goodbye\n");
        //}
        public abstract void SayGoodbye();
    }


    public class DerivedClass : BaseClass
    {
        public new void SayHello()
        {
            Console.WriteLine("Hi There");
        }

        public override void SayGoodbye()
        {
            Console.WriteLine("See you later");
        }
    }

    public class DerivedClass2 : AbstractClass
    {
        public new void SayHello()
        {
            Console.WriteLine("Hi There");
        }
        // We should use the override keyword with abstract types
        //public new void SayGoodbye()
        //{
        //    Console.WriteLine("See you later2");
        //}
        public override void SayGoodbye()
        {
            Console.WriteLine("See you later");
        }
    }
}

6

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ż:

  • W porównaniu z ludźmi maszyny są naprawdę dobre w wyszukiwaniu i sortowaniu
  • W porównaniu z maszynami ludzie są naprawdę dobrzy w wynalazkach i innowacjach

Tak więc krótka odpowiedź brzmi: virtualjest późną instrukcją wiązania dla maszyny (środowiska wykonawczego), podczas gdy abstractjest późną instrukcją wiązania dla człowieka (programisty)

Innymi słowy virtualoznacza:

„Drogi środowisku wykonawczym , powiąż odpowiedni kod z tą nazwą, robiąc to, co robisz najlepiej: wyszukiwanie

abstractOznacza 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 ”.


3

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)


3

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ę.

  • Możemy zmienić typ zwracanej funkcji wirtualnej podczas implementacji
    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.

    public abstract class BaseClass
    { 
        protected abstract void xAbstractMethod();
    
        public virtual void xVirtualMethod()
        {
            var x = 3 + 4;
        }
    } 
    

2

Widziałem w niektórych miejscach metodę abstrakcyjną zdefiniowaną jak poniżej. **

„Metoda abstrakcyjna musi zostać zaimplementowana w klasie potomnej”

** 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.

                                 ----------CODE--------------

public abstract class BaseClass
{
    public int MyProperty { get; set; }
    protected abstract void MyAbstractMethod();

    public virtual void MyVirtualMethod()
    {
        var x = 3 + 4;
    }

}
public abstract class myClassA : BaseClass
{
    public int MyProperty { get; set; }
    //not necessary to implement an abstract method if the child class is also abstract.

    protected override void MyAbstractMethod()
    {
        throw new NotImplementedException();
    }
}
public class myClassB : BaseClass
{
    public int MyProperty { get; set; }
    //You must have to implement the abstract method since this class is not an abstract class.

    protected override void MyAbstractMethod()
    {
        throw new NotImplementedException();
    }
}

2

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:

  1. Znajdź wroga
  2. Zneutralizuj go.
  3. Napij się potem piwa

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:

  1. Znajdź wroga.
  2. Zastrzel go w głowę.
  3. Idź do domu
  4. Napić się piwa

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:

  1. Znajdź wroga.
  2. Aresztuj go z kilkoma oskarżonymi o BS.
  3. Idź do domu
  4. Napić się piwa

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.


2

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.


1

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.


1

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


1

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


1

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.


1

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.


0

W języku C # nie ma żadnych wywołań klas wirtualnych.

Dla funkcji

  1. Funkcja abstrakcyjna ma tylko podpis, klasa napędu powinna zastąpić funkcjonalność.
  2. Funkcja wirtualna zachowa część funkcjonalności, którą klasa napędów może zastąpić zgodnie z wymaganiami

Możesz zdecydować na podstawie swoich wymagań.


0

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.


0

Z tła C ++, C # virtual odpowiada C ++ virtual, podczas gdy metody abstrakcyjne C # odpowiadają funkcji C ++ pure virtual


0

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.


0

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

public interface ExampleInterface {

//    public void MethodBodyInInterfaceNotPossible(){
//    }
    void MethodInInterface();

}

public abstract class AbstractClass {
    public abstract void AbstractMethod();

    //    public abstract void AbstractMethodWithBodyNotPossible(){
    //
    //    };

    //Standard Method CAN be declared in AbstractClass
    public void StandardMethod(){
        System.out.println("Standard Method in AbstractClass (super) runs");
    }
}

public class ConcreteClass
    extends AbstractClass
    implements ExampleInterface{

    //Abstract Method HAS TO be IMPLEMENTED in child class. Implemented by ConcreteClass
    @Override
    public void AbstractMethod() {
        System.out.println("AbstractMethod overridden runs");
    }

    //Standard Method CAN be OVERRIDDEN.
    @Override
    public void StandardMethod() {
        super.StandardMethod();
        System.out.println("StandardMethod overridden in ConcreteClass runs");
    }

    public void ConcreteMethod(){
        System.out.println("Concrete method runs");
    }

    //A method in interface HAS TO be IMPLEMENTED in implementer class.
    @Override
    public void MethodInInterface() {
        System.out.println("MethodInInterface Implemented by ConcreteClass runs");

    //    Cannot declare abstract method in a concrete class
    //    public abstract void AbstractMethodDeclarationInConcreteClassNotPossible(){
    //
    //    }
    }
}

-4

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ć.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.