Gibt es eine Möglichkeit, eine nicht virtuelle Methode zu überschreiben? oder etwas, das ähnliche Ergebnisse liefert (außer eine neue Methode zum Aufrufen der gewünschten Methode zu erstellen)?
Ich möchte eine Methode Microsoft.Xna.Framework.Graphics.GraphicsDevice
mit Blick auf Unit-Tests überschreiben .
c#
overriding
overloading
zfedoran
quelle
quelle
Antworten:
Nein, Sie können eine nicht virtuelle Methode nicht überschreiben. Das Beste, was Sie tun können, ist, die Methode auszublenden, indem Sie eine
new
Methode mit demselben Namen erstellen. Dies ist jedoch nicht ratsam, da dies gegen gute Entwurfsprinzipien verstößt.Aber selbst wenn Sie eine Methode ausblenden, erhalten Sie keine polymorphe Ausführung von Methodenaufrufen, wie dies bei einem echten virtuellen Methodenaufruf der Fall wäre. Betrachten Sie dieses Beispiel:
In diesem Beispiel rufen beide die
M
Methode print aufFoo.M
. Wie Sie sehen können, können Sie mit diesem Ansatz eine neue Implementierung für eine Methode erstellen, solange der Verweis auf dieses Objekt vom richtigen abgeleiteten Typ ist. Das Ausblenden einer Basismethode unterbricht jedoch den Polymorphismus.Ich würde empfehlen, dass Sie Basismethoden nicht auf diese Weise ausblenden.
Ich neige dazu, mich auf die Seite derjenigen zu stellen, die das Standardverhalten von C # bevorzugen, dass Methoden standardmäßig nicht virtuell sind (im Gegensatz zu Java). Ich würde noch weiter gehen und sagen, dass Klassen standardmäßig auch versiegelt werden sollten. Vererbung ist schwer richtig zu entwerfen und die Tatsache, dass es eine Methode gibt, die nicht als virtuell markiert ist, zeigt an, dass der Autor dieser Methode niemals beabsichtigt hat, die Methode zu überschreiben.
Edit: "Ausführungszeit polymorpher Versand" :
Damit meine ich das Standardverhalten, das zur Ausführungszeit auftritt, wenn Sie virtuelle Methoden aufrufen. Nehmen wir zum Beispiel an, dass ich in meinem vorherigen Codebeispiel anstelle einer nicht virtuellen Methode tatsächlich eine virtuelle Methode und eine echte überschriebene Methode definiert habe.
Wenn ich
b.Foo
in diesem Fall anrufen würde, würde die CLR den Objekttyp, auf den dieb
Referenz verweist, korrekt bestimmenBar
und den AnrufM
entsprechend weiterleiten.quelle
Nein, kannst du nicht.
Sie können nur eine virtuelle Methode überschreiben - siehe MSDN hier :
quelle
Wenn die Basisklasse nicht versiegelt ist, können Sie davon erben und eine neue Methode schreiben, die die Basisklasse verbirgt (verwenden Sie das Schlüsselwort "new" in der Methodendeklaration). Andernfalls können Sie es nicht überschreiben, da es nie die Absicht des ursprünglichen Autors war, es zu überschreiben, weshalb es nicht virtuell ist.
quelle
Ich denke, Sie werden verwirrt und überschrieben. Überladen bedeutet, dass Sie zwei oder mehr Methoden mit demselben Namen, aber unterschiedlichen Parametersätzen haben. Überschreiben bedeutet, dass Sie eine andere Implementierung für eine Methode in einer abgeleiteten Klasse haben (wodurch das Verhalten ersetzt oder geändert wird in seiner Basisklasse).
Wenn eine Methode virtuell ist, können Sie sie mit dem Schlüsselwort override in der abgeleiteten Klasse überschreiben. Nicht virtuelle Methoden können die Basisimplementierung jedoch nur ausblenden, indem das neue Schlüsselwort anstelle des Überschreibungsschlüsselworts verwendet wird. Die nicht virtuelle Route ist nutzlos, wenn der Aufrufer über eine als Basistyp eingegebene Variable auf die Methode zugreift, da der Compiler einen statischen Versand an die Basismethode verwenden würde (was bedeutet, dass der Code in Ihrer abgeleiteten Klasse niemals aufgerufen würde).
Nichts hindert Sie daran, einer vorhandenen Klasse eine Überladung hinzuzufügen, aber nur Code, der über Ihre Klasse Bescheid weiß, kann darauf zugreifen.
quelle
Sie können nicht-virtuelle Methoden einer Klasse in C # nicht überschreiben (ohne CLR zu hacken), aber Sie können jede Methode der Schnittstelle überschreiben, die die Klasse implementiert. Bedenken Sie, wir haben nicht versiegelt
Und hier ist eine Demo
quelle
Wenn Sie von einer nicht abgeleiteten Klasse erben, können Sie einfach eine abstrakte Superklasse erstellen und stattdessen stromabwärts davon erben.
quelle
Sie können eine nicht virtuelle Methode nicht überschreiben. Sie können jedoch das
new
Schlüsselwort modifier verwenden, um ähnliche Ergebnisse zu erzielen:Sie sollten auch sicherstellen, dass der Zugriffsmodifikator auch derselbe ist, da Sie sonst später keine Vererbung erhalten. Wenn eine andere Klasse vom Schlüsselwort in erbt, wirkt sich dies nicht auf Objekte aus, die von
Class1
diesemnew
SchlüsselwortClass1
erben, es sei denn, der Zugriffsmodifikator ist derselbe.Wenn der Zugriffsmodifikator nicht identisch ist:
... im Vergleich zu, wenn der Zugriffsmodifikator ist das gleiche:
Wie bereits in einer früheren Antwort erwähnt, ist dies kein gutes Konstruktionsprinzip.
quelle
Es gibt eine Möglichkeit, dies mit einer abstrakten Klasse und einer abstrakten Methode zu erreichen.
Erwägen
Wenn Sie nun verschiedene Versionen der Methode MethodToBeTested () haben möchten, ändern Sie die Klassenbasis in eine abstrakte Klasse und die Methode MethodToBeTested () als abstrakte Methode
Mit der abstrakten Leere MethodToBeTested () kommt ein Problem; Die Implementierung ist weg.
Erstellen Sie daher eine
class DefaultBaseImplementation : Base
, um die Standardimplementierung zu erhalten.Erstellen Sie eine weitere,
class UnitTestImplementation : Base
um eine Unit-Test-Implementierung durchzuführen.Mit diesen 2 neuen Klassen kann die Basisklassenfunktionalität überschrieben werden.
Jetzt haben Sie 2 Klassen implementiert (überschreiben)
MethodToBeTested()
.Sie können die (abgeleitete) Klasse nach Bedarf instanziieren (dh entweder mit Basisimplementierung oder mit Unit-Test-Implementierung).
quelle