Was ist der Unterschied zwischen den Schlüsselwörtern override
und new
in C # beim Definieren von Methoden in Klassenhierarchien?
Die folgende Seite fasst Ihre Frage sehr gut zusammen.
Wissen, wann Override und neue Schlüsselwörter verwendet werden müssen
Zusammenfassung
Überschreiben : Wenn eine Methode einer Basisklasse in einer abgeleiteten Klasse überschrieben wird, wird die Version in der abgeleiteten Klasse verwendet, auch wenn der aufrufende Code nicht "wusste", dass das Objekt eine Instanz der abgeleiteten Klasse war.
Neu : Wenn Sie das neue Schlüsselwort anstelle des Überschreibens verwenden, überschreibt die Methode in der abgeleiteten Klasse die Methode in der Basisklasse nicht, sondern verbirgt sie lediglich.
Wenn Sie weder neu noch Überschreibungen angeben, ist die resultierende Ausgabe dieselbe wie bei Angabe von neu, es wird jedoch auch eine Compiler-Warnung angezeigt (da Sie möglicherweise nicht wissen, dass Sie eine Methode in der Basisklasse ausblenden Methode, oder Sie wollten sie möglicherweise überschreiben und haben lediglich vergessen, das Schlüsselwort anzugeben.
Override : Wird mit der Methode virtual / abstract / override in der Basisklasse verwendet
Neu : Wenn die Basisklasse die Methode nicht als virtuell / abstrakt / überschrieben deklariert hat
new
schattiert die Methode mit einer völlig neuen Methode (die möglicherweise dieselbe Signatur hat oder nicht), anstatt sie zu überschreiben (in diesem Fall muss die neue Methode dieselbe Signatur haben), was bedeutet, dass Polymorphismus nicht funktioniert. Zum Beispiel haben Sie diese Klassen:class A { public virtual int Hello() { return 1; } } class B : A { new public int Hello(object newParam) { return 2; } } class C : A { public override int Hello() { return 3; } }
Wenn du das tust:
A objectA; B objectB = new B(); C objectC = new C(); Console.WriteLine(objectB.Hello(null)); // 2 Console.WriteLine(objectC.Hello()); // 3 objectA = objectB; Console.WriteLine(objectA.Hello()); // 1 objectA = objectC; Console.WriteLine(objectA.Hello()); // 3
Da Sie mit neue Methodensignaturen definieren können, kann
new
der Compiler nicht wissen, dass die Instanz vonA
tatsächlich eine Instanz von istB
und die neuen MethodendefinitionenB
verfügbar sein sollten.new
kann verwendet werden, wenn die Methode, Eigenschaft, das Feld oder das Ereignis des übergeordneten Objekts nicht mit deklariertvirtual
ist undvirtual
die geerbte Methode aufgrund des Fehlens des Compilers nicht "nachgeschlagen" wird. Mitvirtual
undoverride
funktioniert es jedoch.Ich würde Ihnen dringend empfehlen, dies zu vermeiden
new
. Im besten Fall ist es verwirrend, weil Sie eine Methode mit einem Namen definieren, der als etwas anderes erkannt werden könnte. Im schlimmsten Fall kann sie Fehler verbergen, scheinbar unmögliche Fehler verursachen und die Erweiterung der Funktionalität erschweren.quelle
Hello()
, B Variable mit Schnittstellentyp zuweisen). Es wäre gut, dies auch in Ihrer Antwort zu verdeutlichen, da dies die Situation war, nach der ich gesucht habe.Sieht aus wie eine alte Frage, lassen Sie mich eine andere Antwort versuchen:
new
: Wie der Name schon sagt, handelt es sich um ein neues Mitglied in der Familie der Vererbungshierarchien, das als Basismitglied weiter unten in der Kette verwendet wird (sofern es als virtuell markiert ist).override
: Das bedeutet, dass ich die Implementierung der Mitglieder meiner Elternklasse nicht akzeptiere und es anders machen werde.quelle
Betrachten Sie die folgende Klassenhierarchie:
using System; namespace ConsoleApp { public static class Program { public static void Main(string[] args) { Overrider overrider = new Overrider(); Base base1 = overrider; overrider.Foo(); base1.Foo(); Hider hider = new Hider(); Base base2 = hider; hider.Foo(); base2.Foo(); } } public class Base { public virtual void Foo() { Console.WriteLine("Base => Foo"); } } public class Overrider : Base { public override void Foo() { Console.WriteLine("Overrider => Foo"); } } public class Hider : Base { public new void Foo() { Console.WriteLine("Hider => Foo"); } } }
Die Ausgabe der obigen Codes muss sein:
quelle
Program
Klasse und andere Klassen in zwei separate Codeblöcke aufteilen , wobei die Ausgabe dem Methodenaufruf als Kommentar entspricht, zbase2.Foo(); // Base => Foo
. Ich würde auch den Namespace weglassenoverride
Mit dieser Option können Sie eine virtuelle Methode in einer Basisklasse überschreiben, sodass Sie eine andere Implementierung einfügen können.new
Dadurch wird eine nicht virtuelle Methode in einer Basisklasse ausgeblendet.quelle
new
es sich um eine völlig unabhängige Methode handelt, die zufällig denselben Namen hat.