Frage Was ist der Unterschied zwischen einer abstrakten Funktion und einer virtuellen Funktion?


Was ist der Unterschied zwischen einer abstrakten Funktion und einer virtuellen Funktion? In welchen Fällen empfiehlt es sich, virtuell oder abstrakt zu verwenden? Welcher ist der richtige Ansatz?


1304
2017-12-24 14:11


Ursprung


Antworten:


Eine abstrakte Funktion kann keine Funktionalität haben. Sie sagen im Grunde, dass jede untergeordnete Klasse ihre eigene Version dieser Methode angeben muss, jedoch ist sie zu allgemein, um sie sogar in der übergeordneten Klasse implementieren zu können.

Eine virtuelle Funktion, im Grunde gesagt, schau, hier ist die Funktionalität, die für die Kindklasse gut genug sein kann oder auch nicht. Also, wenn es gut genug ist, benutze diese Methode, wenn nicht, dann überschreibe mich und stelle deine eigene Funktionalität zur Verfügung.


2325
2017-12-24 14:14



Eine abstrakte Funktion hat keine Implementierung und kann nur für eine abstrakte Klasse deklariert werden. Dies zwingt die abgeleitete Klasse, eine Implementierung bereitzustellen. Eine virtuelle Funktion stellt eine Standardimplementierung bereit und kann entweder in einer abstrakten Klasse oder in einer nicht abstrakten Klasse vorhanden sein. Also zum Beispiel:

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

244
2017-12-24 14:19



  1. Nur abstract Klassen können haben abstract Mitglieder.
  2. Ein nichtabstract Klasse, die von einem erbt abstract Klasse Muss  override es ist abstract Mitglieder.
  3. Ein abstract Mitglied ist implizit virtual.
  4. Ein abstract Mitglied kann keine Implementierung bereitstellen (abstract wird genannt pure virtual in einigen Sprachen).

68
2018-04-16 09:03



Sie müssen eine abstrakte Funktion immer überschreiben.

So:

  • Abstrakte Funktionen - wann Der Vererber muss eine eigene Implementierung bereitstellen
  • Virtuell - wann Es liegt in der Verantwortung des Erben zu entscheiden

49
2017-12-24 14:13



Abstrakte Funktion:

  1. Es kann nur innerhalb der abstrakten Klasse deklariert werden.
  2. Es enthält nur Methodendeklaration nicht die Implementierung in der abstrakten Klasse.
  3. Es muss in der abgeleiteten Klasse überschrieben werden.

Virtuelle Funktion:

  1. Es kann sowohl in der abstrakten als auch in der nicht abstrakten Klasse deklariert werden.
  2. Es enthält Methodenimplementierung.
  3. Es kann überschrieben werden.

30
2018-05-28 07:52



Abstrakte Methode: Wenn eine Klasse eine abstrakte Methode enthält, muss diese Klasse als abstrakt deklariert werden. Die abstrakte Methode hat keine Implementierung und daher müssen Klassen, die von dieser abstrakten Klasse abgeleitet sind, eine Implementierung für diese abstrakte Methode bereitstellen.

Virtuelle Methode: Eine Klasse kann eine virtuelle Methode haben. Die virtuelle Methode hat eine Implementierung. Wenn Sie von einer Klasse mit einer virtuellen Methode erben kann Überschreiben Sie die virtuelle Methode und stellen Sie zusätzliche Logik bereit oder ersetzen Sie die Logik durch Ihre eigene Implementierung.

Wann zu verwenden was: In einigen Fällen wissen Sie, dass bestimmte Typen eine bestimmte Methode haben sollten, aber Sie wissen nicht, welche Implementierung diese Methode haben soll.
In solchen Fällen können Sie eine Schnittstelle erstellen, die eine Methode mit dieser Signatur enthält. Wenn Sie jedoch einen solchen Fall haben, aber Sie wissen, dass die Implementierer dieser Schnittstelle auch eine andere allgemeine Methode haben (für die Sie die Implementierung bereits bereitstellen können), können Sie eine abstrakte Klasse erstellen. Diese abstrakte Klasse enthält dann die abstrakte Methode (die überschrieben werden muss) und eine andere Methode, die die "gemeinsame" Logik enthält.

Eine virtuelle Methode sollte verwendet werden, wenn Sie eine Klasse haben, die direkt verwendet werden kann, für die Sie jedoch ein bestimmtes Verhalten ändern können, obwohl dies nicht zwingend erforderlich ist.


27
2018-04-16 09:03



Erklärung: mit Analogien. Hoffentlich wird es dir helfen.

Kontext

Ich arbeite im 21. Stock eines Gebäudes. Und ich bin paranoid von Feuer. Hin und wieder, irgendwo auf der Welt, brennt ein Feuer einen Wolkenkratzer nieder. Aber glücklicherweise haben wir hier irgendwo eine Anleitung, was man im Brandfall machen kann:

Notausgang()

  1. Sammle keine Sachen
  2. Gehe zum Fluchtweg
  3. Geh aus dem Gebäude

Dies ist im Grunde eine virtuelle Methode namens Notausgang()

Virtuelle Methode

Dieser Plan ist ziemlich gut für 99% der Umstände. Es ist ein grundlegender Plan, der funktioniert. Aber es besteht eine 1% ige Chance, dass die Feuerleiter blockiert oder beschädigt wird. In diesem Fall werden Sie komplett verschraubt und Sie werden zu Toast, wenn Sie nicht drastische Maßnahmen ergreifen. Mit virtuellen Methoden können Sie genau das tun: Sie können den grundlegenden FireEscape () -Plan mit Ihrer eigenen Version des Plans überschreiben:

  1. Zum Fenster laufen
  2. Springe aus dem Fenster
  3. Fallschirm sicher auf den Boden

Mit anderen Worten Virtuelle Methoden bieten einen grundlegenden Plan, der bei Bedarf überschrieben werden kann. Unterklassen können die virtuelle Methode der übergeordneten Klasse überschreiben, wenn der Programmierer dies für angemessen hält.

Abstrakte Methoden

Nicht alle Organisationen sind gut ausgebildet. Einige Organisationen führen keine Brandschutzübungen durch. Sie haben keine allgemeine Fluchtpolitik. Jeder ist für sich selbst. Das Management ist nur an einer solchen Politik interessiert.

Mit anderen Worten, jede Person ist gezwungen um seine eigene FireEscape () -Methode zu entwickeln. Ein Typ wird die Feuerleiter verlassen. Ein anderer Typ wird Fallschirm springen. Ein anderer wird mit Raketenantriebstechnik vom Gebäude wegfliegen. Ein anderer Typ wird abseilen. Management ist es egal Wie Sie entkommen, solange Sie einen grundlegenden FireEscape () -Plan haben - wenn sie das nicht tun, können Sie sicher sein, dass OHS wie eine Tonne Ziegel auf die Organisation herunterkommen wird. Dies ist mit einer abstrakten Methode gemeint.

Was ist der Unterschied zwischen den beiden wieder?

Abstrakte Methode: Unterklassen sind gezwungen um eine eigene FireEscape-Methode zu implementieren. Mit einer virtuellen Methode haben Sie einen Basisplan, der auf Sie wartet, aber Sie können wählen um dein eigenes zu implementieren wenn es nicht gut genug ist.

Nun, das war nicht so schwer, oder?


23
2018-06-16 01:01



Eine abstrakte Methode ist eine Methode, die implementiert werden muss, um eine konkrete Klasse zu erstellen. Die Deklaration befindet sich in der abstrakten Klasse (und jede Klasse mit einer abstrakten Methode muss eine abstrakte Klasse sein) und muss in einer konkreten Klasse implementiert werden.

Eine virtuelle Methode ist eine Methode, die in einer abgeleiteten Klasse mithilfe der Überschreibung überschrieben werden kann. ersetzen das Verhalten in der Oberklasse. Wenn Sie nicht überschreiben, erhalten Sie das ursprüngliche Verhalten. Wenn Sie das tun, erhalten Sie immer das neue Verhalten. Dies steht im Gegensatz zu nicht virtuellen Methoden, die nicht überschrieben werden können, aber die ursprüngliche Methode verbergen können. Dies geschieht mit dem newModifikator.

Siehe das folgende Beispiel:

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");
    }
}

Wenn ich instanziiere DerivedClass und Ruf an SayHello, oder SayGoodbyeIch bekomme "Hi There" und "Bis später". Wenn ich anrufe HelloGoodbyeIch bekomme "Hallo" und "Bis später". Das ist weil SayGoodbye ist virtuell und kann durch abgeleitete Klassen ersetzt werden. SayHello ist nur versteckt, also wenn ich das von meiner Basisklasse anrufe, bekomme ich meine ursprüngliche Methode.

Abstrakte Methoden sind implizit virtuell. Sie definieren Verhalten, das vorhanden sein muss, mehr wie eine Schnittstelle.


21
2018-04-16 09:13



Abstrakte Methoden sind immer virtuell. Sie können keine Implementierung haben.

Das ist der Hauptunterschied.

Im Grunde genommen würden Sie eine virtuelle Methode verwenden, wenn Sie die 'Standard' -Implementierung davon haben und den Nachkommen erlauben wollen, ihr Verhalten zu ändern.

Mit einer abstrakten Methode erzwingen Sie, dass Nachkommen eine Implementierung bereitstellen.


9
2018-04-16 09:00



Ich habe dies vereinfacht, indem ich einige Verbesserungen an den folgenden Klassen vorgenommen habe (aus anderen Antworten):

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");
        }
    }
}

9
2017-12-07 09:14