2010-06-01 12 views
25

Ich habe die folgenden Klassen:Verwirrt über "überschreiben" vs. "neu" in C#

class Base 
{ 
    public virtual void Print() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

class Der1 : Base 
{ 
    public new virtual void Print() 
    { 
     Console.WriteLine("Der1"); 
    } 
} 

class Der2 : Der1 
{ 
    public override void Print() 
    { 
     Console.WriteLine("Der2"); 
    } 
} 

Das ist meine Hauptmethode ist:

Base b = new Der2(); 
Der1 d1 = new Der2(); 
Der2 d2 = new Der2(); 

b.Print(); 
d1.Print(); 
d2.Print(); 

Der Ausgang ist Base, Der2, Der2.

Soweit ich weiß, lässt Override die vorherige Methode nicht laufen, auch wenn der Zeiger auf sie zeigt. Daher sollte die erste Zeile auch Der2 ausgeben. Jedoch kam Base heraus.

Wie ist es möglich? Wie hat die Überschreibung dort nicht funktioniert?

+0

wirklich ein tolles Beispiel ... Der einzige Trick ist: - intially, Methode von BASE Jahren wurde durch die virtuelle Methode der "Der-1" versteckt, so over-ride Methode des „Des-2 "konnte nicht implementiert werden. Somit haben wir den BASE-Wert erhalten. – Kings

Antwort

27

Sie haben die Base Version von Print() niemals überschrieben. Sie haben es nur mit einer separaten virtuellen Methode (gleich benannt) in Der1 ausgeblendet.

Wenn Sie das Schlüsselwort 10 für eine Methodensignatur verwenden, sagen Sie dem Compiler, dass dies eine Methode ist, die zufällig den gleichen Namen wie eine Methode einer Ihrer Basisklassen hat, aber keine andere Beziehung hat. Sie können diese neue Methode virtuell machen (wie Sie es getan haben), aber das ist nicht dasselbe wie das Überschreiben der Basisklassenmethode.

In Der2 wenn Sie Print außer Kraft setzen Sie überschreiben tatsächlich die ‚neue‘ Version, die Sie in Der1 erklärt - nicht die Version Base ist. Eric Lippert hat eine excellent answer zu einer etwas anderen Frage, die Ihnen helfen kann, darüber nachzudenken, wie virtuelle Methoden in der C# -Sprache behandelt werden.

In Ihrem Beispiel, wenn Sie Print nennen, können Sie es im ersten Fall durch eine Referenz des Typs Base fordern - so die versteckte (aber nicht außer Kraft gesetzt) ​​Version von Print aufgerufen. Die anderen beiden Aufrufe werden an die Implementierung Der1 gesendet, da Sie in diesem Fall die Methode tatsächlich überschrieben haben.

Sie können mehr darüber in der MSDN documentation of new and override lesen.

Was haben Sie bestimmt mit Der1 zu tun (wie Sie mit der2 tat) ist das override Schlüsselwort zu verwenden:

class Base 
{ 
    public virtual void Print() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

class Der1 : Base 
{ 
    // omitting 'new' and using override here will override Base 
    public override void Print() 
    { 
     Console.WriteLine("Der1"); 
    } 
} 
+0

Das hat er mit Der2 gemacht. – GalacticCowboy

+0

@GalacticCowboy - das war mein Punkt. Das war wahrscheinlich auch in Der1 beabsichtigt, aber irgendwie wurde das 'new'-Schlüsselwort eingefügt, anstatt' override'. Ich werde meinen Beitrag aktualisieren, um das klarer zu machen. – LBushkin

+0

Danke. Eine wunderbare Antwort, ich habe völlig verstanden, wie es jetzt funktioniert. – iTayb

5

Es ist, weil Der1 nicht ÜberschreibungPrint, sie es mit einem ersetzt brandneue Methode, die zufällig den gleichen Namen hat (dies wird durch die Verwendung des Schlüsselwortes new verursacht). Wenn das Objekt in Base umgewandelt wird, ruft es Print in Base auf; Es gibt keine Außerkraftsetzung zum Anrufen ..

1

override das vorherige Verfahren ersetzen, sondern als Der1 Klasse Print() nicht außer Kraft setzen (es Shadows es, eine VB-ism zu verwenden), dann die meist überschriebenen verion von Base ‚s Print() genannt wird, was geschieht sei die Version, die es definiert

0

Wie alle gesagt haben, ersetzt die Klasse Der1Print() anstatt es zu überschreiben. Um dies in Aktion zu sehen, können Sie d1 und d2 auf Base basieren und dann die Druckmethode aufrufen. Es wird dann Base zurückgeben.

((Base)d2).Print(); //Base