Was sind virtuelle Methoden?


80

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

Was ist der Vorteil bei der Verwendung von Virtual?

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

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.


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.


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.

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.


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.


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.


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.


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 .



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

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

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


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.