Was sind virtuelle Methoden?

80

Warum würden Sie eine Methode als "virtuell" deklarieren?

Was ist der Vorteil bei der Verwendung von Virtual?

HerbalMart
quelle

Antworten:

58

Der virtuelle Modifikator wird verwendet, um zu markieren, dass eine Methode \ Eigenschaft (ect) in einer abgeleiteten Klasse mithilfe des Überschreibungsmodifikators geändert werden kann .

Beispiel:

class A
{
    public virtual void Foo()
       //DoStuff For A
}

class B : A
{
    public override void Foo()
    //DoStuff For B

    //now call the base to do the stuff for A and B 
    //if required
    base.Foo()
}
cgreeno
quelle
43

Mit Virtual kann eine erbende Klasse eine Methode ersetzen, die die Basisklasse dann verwendet.

public class Thingy
{
    public virtual void StepA()
    {
        Console.Out.WriteLine("Zing");
    }

    public void Action()
    {
        StepA();
        Console.Out.WriteLine("A Thingy in Action.");
    }
}

public class Widget : Thingy
{
    public override void StepA()
    {
        Console.Out.WriteLine("Wiggy");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Thingy thingy = new Thingy();
        Widget widget = new Widget();

        thingy.Action();
        widget.Action();

        Console.Out.WriteLine("Press any key to quit.");
        Console.ReadKey();
    }
 }

Wenn Sie das Programm ausführen, wird Folgendes ausgegeben:

Zing 
A Thingy in Action. 
Wiggy 
A Thingy in Action.

Beachten Sie, dass Widget zwar die auf Thingy-Ebene definierte Action () -Methode aufgerufen hat, Thingy jedoch intern die StepA () -Methode von Widget aufgerufen hat.

Die grundlegende Antwort ist, dass es Erben einer Klasse mehr Flexibilität gibt. Natürlich musst du deine Klasse gut konstruieren, sonst könnte es zu einem schwachen Chaos kommen.

Ludington
quelle
23

Eine virtuelle Methode ist eine Art von Methode, bei der die tatsächlichen Methodenaufrufe vom Laufzeittyp des zugrunde liegenden Objekts abhängen.

Eine nicht virtuelle Methode ist ein Methodentyp, bei dem die tatsächlich aufgerufene Methode vom Referenztyp des Objekts zum Zeitpunkt des Methodenaufrufs abhängt.

JaredPar
quelle
Dies sollte eine Antwort sein - virtuell kann nicht über die Änderungsbedingungen der Deklaration definiert werden. Wie unterscheidet es sich dann von der Methode, die sich versteckt?
SENya
13

Virtuelle Methoden auf MSDN

Das virtuelle Schlüsselwort wird verwendet, um eine Methode oder eine Eigenschaftsdeklaration zu ändern. In diesem Fall wird die Methode oder die Eigenschaft als virtuelles Mitglied bezeichnet. Die Implementierung eines virtuellen Mitglieds kann von einem überschreibenden Mitglied in einer abgeleiteten Klasse geändert werden.

Wenn eine virtuelle Methode aufgerufen wird, wird der Laufzeittyp des Objekts auf ein überschreibendes Mitglied überprüft. Das überschreibende Mitglied in der am meisten abgeleiteten Klasse wird aufgerufen. Dies kann das ursprüngliche Mitglied sein, wenn keine abgeleitete Klasse das Mitglied überschrieben hat. (Weitere Informationen zum Laufzeittyp und zur am häufigsten abgeleiteten Implementierung finden Sie unter 10.5.3 Virtuelle Methoden.)

Standardmäßig sind Methoden nicht virtuell. Sie können eine nicht virtuelle Methode nicht überschreiben.

Sie können den virtuellen Modifikator nicht mit den folgenden Modifikatoren verwenden:

statische abstrakte Überschreibung

Virtuelle Eigenschaften verhalten sich wie abstrakte Methoden, mit Ausnahme der Unterschiede in der Deklarations- und Aufrufsyntax.

  • Es ist ein Fehler, den virtuellen Modifikator für eine statische Eigenschaft zu verwenden.
  • Eine virtuelle geerbte Eigenschaft kann in einer abgeleiteten Klasse überschrieben werden, indem eine Eigenschaftsdeklaration eingefügt wird, die den Überschreibungsmodifikator verwendet.
Russ Cam
quelle
6

Auch wenn Sie nicht vorhaben, von der Klasse abzuleiten, kann es erforderlich sein, die Methode als virtuell zu markieren, um die Klasse zu verspotten. Bei einigen Mocking-Frameworks können Sie nur virtuelle Methoden verspotten. Beachten Sie, dass Methoden, die eine Schnittstelle implementieren, implizit virtuell sind.

Ich verwende RhinoMocks, das diese Einschränkung aufweist, und habe aus diesem Grund meine Methoden standardmäßig als virtuell markiert. Für mich ist dies wahrscheinlich der größte Grund, virtuelle Methoden zu verwenden, da die Fälle, in denen die Vererbung ins Spiel kommt, viel seltener sind.

Tvanfosson
quelle
5

Virtuelle Methoden ähneln abstrakten Methoden in Basisklassen, außer dass ihre Implementierung in abgeleiteten Klassen optional ist. Sie können auch Logik in virtuelle Methoden einfügen und diese in abgeleiteten Klassen überschreiben.

Cyclo
quelle
3

Um es beim Erben von Klassen überschreiben zu können.

Überprüfen Sie den MSDN-Eintrag für das Schlüsselwort. Das erklärt es ausführlicher.

PHeiberg
quelle
3

Eine kurze Frage, eine kurze Antwort! Qualifizieren Sie Ihre Methode als "virtuell", wenn Sie glauben, dass Sie die Klasse erben werden, zu der sie gehört.

Eine längere Antwort: "Mit Virtual können Sie überschreiben und Ihrer Methode in einer abgeleiteten Klasse eine andere Bedeutung geben.

Stephane Halimi
quelle
1

Es ist unnötig zu erwähnen, dass virtuelle Methoden nützlich sind, wenn Ihr Code versucht, das Open Closed-Prinzip einzuhalten

Lesen Sie mehr über das Open-Closed-Prinzip hier , Onkel Bob Original OCP White Paper.

Bitte beachten Sie auch, dass Methoden in C # im Gegensatz zu Java nicht standardmäßig virtuell sind .

abhilash
quelle
1

Hier wird dies anhand des Beispiels C # Virtual Method klar erläutert

Hitsa
quelle
1

Virtuelle Funktionen sind die Funktionen, die nicht wirklich existieren. Die abgeleitete Klasse kann die virtuelle Funktion durch Überschreiben ändern. Virtuelle Funktionen sind eine der Möglichkeiten, um Laufzeitpolymorphismus zu erzielen

    public class sample {
      public virtual void fun(){
        Console.WriteLine("base sample class \n");
      }
    }
    public class A : sample{
      public override void fun(){
        Console.WriteLine("Class A \n");
      }
    }
    public class B : sample{
      public override void fun(){
        Console.WriteLine("Class B \n");
      }
    }
    class run{
      public static void main(String[] args){
        sample obj = new sample();
        sample obj1 = new A();
        sample obj2 = new B();
        obj.fun();
        obj1.fun();
        obj2.fun();
      }
    }
Lineesh K Mohan
quelle
Was meinst du mit "existiert nicht wirklich"? Könnten Sie eine Referenz geben
Mubarek
Dies sieht nicht nach C # -Vererbung aus. Die publicZugriffsmodifikatoren nach class Aund class Bverursachen Fehler bei der Kompilierung. Die Zugänglichkeit von Mitgliedern in der Basisklasse aus der abgeleiteten Klasse wird auf individueller Basis von der Basisklasse festgelegt (standardmäßig sind Mitglieder private).
Minh Tran
@ Minh Tran - Ja, Sie sind richtig. Das war C ++ - Vererbung. Wie auch immer, ich habe den Beitrag bearbeitet.
Lineesh K Mohan
1

Die Laufzeit erfolgt über die Kompilierungszeit.
Wenn Sie eine Methode als virtuell deklarieren, müssen Sie zum Deklarieren in einer abgeleiteten Klasse einen overrideoder einen newModifikator hinzufügen .
wir können das sehen wenn TrySpeak. Bei der Übergabe von Kind und Vater rufen beide Speak of Father auf, während TryScreamjede Methode aufgerufen wird.
Um dies zu verstehen, gibt es einige Dinge, die wir in einem Fall von Kind wissen sollten. Es gibt zwei ScreamMethoden aus der Kinderklasse oder der Vaterklasse. Wir könnten entweder die Scream Klasse von Kind oder Vater anrufen . Da der VirtaulModifikator die Methode markiert, damit sie von der abgeleiteten Klasse überschrieben werden kann, was bedeutet, dass selbst die Screamvon der Vater-Klasse aufgerufene Klasse überschrieben wird, wäre es anders, wenn Sie einen neuen Modifikator verwenden.

import system;
class Father
{
    Speak()
    {
        Console.Writeline("Father is speaking") 
    }
    virtual Scream()
    {
        Console.Writeline("Father is screaming")    
    }
}
class Child: father
{
    Speak()
    {
        Console.Writeline("Child is speaking")  
    }
    override Scream()
    {
        Console.Writeline("Child is screaming") 
    }
}
class APP
{
    public static void Main()
    {
        // We new two instances here
        Father father = new Father();
        Child child = new Child();        
        // Here we call their scream or speak through TryScream or TrySpeak
        TrySpeak(father);
        TrySpeak(child);
        //>>>"Father is speaking"
        //>>>"Father is speaking"
        TryScream(father);
        TryScream(child);
        //>>>"Father is screaming"
        //>>>"Child is screaming"
    }
    // when your method take an Parameter who type is Father
    // You can either pass in a Father instance or
    // A instance of a derived Class from Father
    // which could be Child
    public static void TrySpeak(Father person)
    {
        person.Scream();
    }
    public static void TryScream(Father person)
    {
        person.Speak();
    }
}
Seelenmond
quelle
1

In C # müssen Sie zum Überschreiben der Basisklassenmethode in der abgeleiteten Klasse die Basisklassenmethode als virtuelle und die abgeleitete Klassenmethode als Überschreibung deklarieren, wie unten gezeigt:

using System;
namespace Polymorphism
{
 class A
 {
 public virtual void Test() { Console.WriteLine("A::Test()"); }
 }

 class B : A
 {
 public override void Test() { Console.WriteLine("B::Test()"); }
 }

 class C : B
 {
 public override void Test() { Console.WriteLine("C::Test()"); }
 }

 class Program
 {
 static void Main(string[] args)
 {

 A a = new A();
 B b = new B();
 C c = new C();
 a.Test(); // output --> "A::Test()"
 b.Test(); // output --> "B::Test()"
 c.Test(); // output --> "C::Test()"

 a = new B();
 a.Test(); // output --> "B::Test()"

 b = new C();
 b.Test(); // output --> "C::Test()"

 Console.ReadKey();
 }
 }
}

Sie können das Ausblenden von Methoden und das Überschreiben von Methoden auch mithilfe eines virtuellen und eines neuen Schlüsselworts mischen, da die Methode einer abgeleiteten Klasse gleichzeitig virtuell und neu sein kann. Dies ist erforderlich, wenn Sie die abgeleitete Klassenmethode in der nächsten Ebene weiter überschreiben möchten, da ich die Klasse B, Test () -Methode in Klasse C wie unten beschrieben überschreibe:

using System;
namespace Polymorphism
{
 class A
 {
 public void Test() { Console.WriteLine("A::Test()"); }
 }

 class B : A
 {
 public new virtual void Test() { Console.WriteLine("B::Test()"); }
 }

 class C : B
 {
 public override void Test() { Console.WriteLine("C::Test()"); }
 }

 class Program
 {
 static void Main(string[] args)
 {

 A a = new A();
 B b = new B();
 C c = new C();

 a.Test(); // output --> "A::Test()"
 b.Test(); // output --> "B::Test()"
 c.Test(); // output --> "C::Test()"

 a = new B();
 a.Test(); // output --> "A::Test()"

 b = new C();
 b.Test(); // output --> "C::Test()"

 Console.ReadKey();
 }
 }
}

GOLDENE WÖRTER: Mit dem virtuellen Schlüsselwort werden eine in der Basisklasse deklarierte Methode, Eigenschaft, ein Indexer oder ein Ereignis geändert und in der abgeleiteten Klasse überschrieben.

Das Schlüsselwort override wird verwendet, um eine virtuelle / abstrakte Methode, Eigenschaft, einen Indexer oder ein Ereignis der Basisklasse in eine abgeleitete Klasse zu erweitern oder zu ändern.

Das neue Schlüsselwort wird verwendet, um eine Methode, eine Eigenschaft, einen Indexer oder ein Ereignis der Basisklasse in einer abgeleiteten Klasse auszublenden.

GENIESSEN :-)

Rana Bhopale
quelle
-1

Dieser Link bietet Ihnen ein besseres Verständnis mit einem sehr einfachen Beispiel: https://stackoverflow.com/a/2392656/3373865

Anand Kumar Jha
quelle
1
Dies ist nicht nur eine Nur-Link-Antwort (bitte geben Sie den Inhalt des verlinkten Beitrags in Ihrer Antwort an, falls der Link unterbrochen wird), sondern auch C ++, nicht C #. Treffen hier die gleichen Grundsätze zu?
Marks Polakovs