Frage zu "Virtual" und "Override"



  • Hallo,

    bin gerade am Anfang von C#, hab gerade eine Übung zu Vererbung von Klassen gemacht, soweit oK.

    1.)
    Hier wurde erklärt, das eine Methode (z.B. "Ausgabe") in der abgeleiteten Klasse mit new gekennzeichnet, da in der Basisklasse eine Methode mit gleichem Namen existiert.

    class Fahrzeug
    {
       public string ausgabe() 
       {
          return "Geschwindigkeit: " + geschwindigkeit + "\n";
       }
    }
    
    class PKW : Fahrezug
    {
       public new string ausgabe()
       {
          return "Insassen: " + insassen + "\n" + base.ausgabe();
       }
    }
    

    2.)
    In dem aktuellen Kapitel geht es dann darum, dass in der Basisklasse ine Methode (z.B. "Ausgabe") als virtual angelegt ist. Nun wird in der Basisklasse ebenfalls eine Methode mit dem Namen "Ausgabe" angelegt. Hier wird die dann aber mit Override angegeben. Irgendwie versteh ich den Unterschied aber nicht.

    class Fahrzeug
        {
    
            public virtual string ausgabe()
            {
                return"\n" + 
                    "Bezeichnung: " + bezeichnung + "\n" +
                    "Geschwindigkeit: " + geschwindigkeit + "\n";
            }
        }
    
        class PKW : Fahrzeug
        {
            public override string ausgabe()
            {
                return base.ausgabe() + "Insassen: " + insassen + "\n";
            }
        }
    

    In beiden Fällen wird doch die Methode Ausgabe (abgeleitete KLasse), sowie die Methode der Basisklasse aufgerufen, wo liegt denn da der Unterschied/Vorteil?



  • Der Unterschied ist erst sichtbar bei

    PKW pkw = new PKW ();
    Fahrzeug fahrzeug = pkw;
    fahrzeug->ausgabe(); //!!
    

    Wenn die Methode des Parents nur ausgeblendet wurde (mit new) dann rufst du mit diesem Code die Methode des Parents auf.
    Wenn du die virtuelle Methdoe allerdings überschrieben hast rufst du die Methode des Childs auf.
    Und das ist der Unterschied 😉



  • Danke für die schnelle Antwort, Verstanden habe ich das allerdings nicht.

    Wenn ich doch im Fall 2 die Riehen Folge ändere sieht die Zeile in beiden Fällen gleich aus. Die Ausgabe ist dann doch auch die gleiche.

    Hab jetzt irgendwie ein mächtiges Brett vorm Kopf 😮

    Hoffe DU hast nich die Nerven es anders zu Versuchen. Vielleicht ist ja auch das Beispiel schlecht....

    Vielen Dank schon mal im Voraus



  • new als Element-Modifier (also auf Methoden, Variablen, Properties usw. angewandt) stellt eine explizite Ausblendung des gleichen Members aus der Basisklasse dar. Ich schreibe deshalb explizit, weil das auch implizit - also ohne new - funktioniert. Schau dir dazu mal den Artikel in der msdn an: http://msdn.microsoft.com/en-us/library/435f1dw2(v=vs.80).aspx

    Des Weiteren muss dir der Unterschied zwischen dem statischen und dynamischen Typ einer Instanz bewusst sein. Betrachten wir mal das hier:

    class Base {
    	public void Foo() {
    		Console.WriteLine("I'm Base.Foo");
    	}
    
    	public virtual void Bar() {
    		Console.WriteLine("I'm Base.Bar");
    	}
    }
    
    class Sub : Base {
    	public new void Foo() {
    		Console.WriteLine("I'm Sub.Foo");
    	}
    
    	public override void Bar() {
    		Console.WriteLine("I'm Sub.Bar");
    	}
    }
    
    void Main()
    {
    	Base b = new Base();		//Statischer Typ: Base, Dynamischer Typ: Base
    	b.Foo();
    	b.Bar();
    	Console.WriteLine("");	
    
    	Sub s = new Sub();			//Statischer Typ: Sub, Dynamischer Typ: Sub
    	s.Foo();
    	s.Bar();
    	Console.WriteLine("");
    
    	Base bs = new Sub();		//Statischer Typ: Base, Dynamischer Typ: Sub
    	bs.Foo();
    	bs.Bar();
    	Console.WriteLine("");
    }
    

    Ausgabe:

    I'm Base.Foo
    I'm Base.Bar
    
    I'm Sub.Foo
    I'm Sub.Bar
    
    I'm Base.Foo
    I'm Sub.Bar
    

    Der statische Typ einer Instanz ist immer gleich (wenn du so willst, ist der statische Typ der, der links vom Istgleich-Zeichen bei der Instantiierung steht). Der dynamische kann sich aber ändern (der dynamische Typ ist der, der rechts vom Istgleich-Zeichen steht).
    So kann im obigen Beispiel die Variable "bs" auch auf eine andere, von Base abgeleitete, Klasse zeigen. Wenn dann Bar aufgerufen wird, wird bei virtual-Methoden entsprechend des dynamischen Typs aufgelöst, welche konkrete Methode denn nun tatsächlich aufgerufen werden soll.
    Normale Methoden werden hingegen immer auf Basis des statischen Typs aufgelöst. Deshalb wird bei s.Foo() auch die Variante "Sub.Foo" aufgerufen. Und bei bs.Foo() eben die der Basisklasse.



  • Vielen Dank mit der Antwort, ich denke hier komme ich jetzt weiter 🙂 👍


Log in to reply