Methoden, die von einer Schnittstelle implementiert werden, sind nicht virtuellen standardmäßig. Sie stellen lediglich eine Implementierung des in der Schnittstellendefinition definierten Vertrags zur Verfügung. Indem Sie die Methode als virtual
markieren, ermöglichen Sie abgeleiteten Klassen, zusätzliche oder separate Implementierungen bereitzustellen und gleichzeitig den definierten Vertrag einzuhalten.
Betrachten Sie dieses Beispiel:
interface IAnimal
{
string Speak();
}
class Dog : IAnimal
{
public string Speak()
{
return "Bark!";
}
}
Die Dog
Klasse ist die Schnittstelle, indem eine Durchführung des Vertrages Umsetzung IAnimal
. Es gibt hier keine virtuellen Methoden und kein Überschreiben.
Betrachten wir nun dieses Beispiel:
interface IAnimal
{
string Speak();
}
class Dog : IAnimal
{
public virtual string Speak()
{
return "Bark!";
}
}
class GoldenRetriever : Dog
{
public override string Speak()
{
return "I am a golden retriever who says "
+ base.Speak();
}
}
Nun ist die Dog
Klasse hat Speak
erklärt virtual
zu sein, die Klassen abgeleitet ermöglicht eine zusätzliche oder neue Implementierung zur Verfügung zu stellen. Dies bricht den Vertrag mit IAnimal
nicht, da jeder Aufruf der Speak
-Methode immer noch eine Zeichenfolge zurückgibt.
Ok, ein letztes Beispiel. Denken Sie daran, dass Schnittstellen keine Implementierung erfordern - sie erfordern lediglich, dass der Vertrag erfüllt wird. Dies bedeutet, dass die Schnittstelle nur darauf achtet, dass ein Member in der implementierenden Klasse existiert, die eine übereinstimmende Signatur aufweist. Das bedeutet, dass wir konnten auch dies tun:
interface IAnimal
{
string Speak();
}
abstract class Dog : IAnimal
{
public abstract string Speak();
}
class GoldenRetriever : Dog
{
public override string Speak()
{
return "I am a golden retriever";
}
}
Hinweis nun, dass die Dog
Klasse überhaupt keine Umsetzung für Speak
bietet noch den Anforderungen des Vertrages erfüllt.
Schnittstellen sind ebenfalls von Klasse zu Klasse geerbt so in allen Beispielen sowohl über Dog
und GoldenRetriever
den IAnimal
-Schnittstelle implementieren. Weder Klasse verstecken die Speak
Methode - beide Klassen implementieren es.
Ok, ich denke, Ihre Verwirrung kann von der Tatsache herrühren, dass die virtuelle Methode in einer Schnittstelle definiert ist, nicht in einer Klasse.Hier ist die IL für die Schnittstelle I oben definiert:
.class private interface abstract auto ansi IAnimal
{
.method public hidebysig newslot abstract
virtual instance string Speak() cil managed
{
}
}
Während Sie richtig sind, dass die Methode definiert ist als virtual
Sie müssen auch feststellen, dass die Art hier als interface
bezeichnet wird. Dies ist nur ein Implementierungsdetail der MSIL, die von Microsoft's C# -Compiler erzeugt wird - ein anderer Compiler könnte leicht anderen Code erzeugen, solange er semantisch das gleiche Ergebnis liefert.
Die wichtige Sache hier ist dies: obwohl die Methode als virtual
in der Schnittstelle deklariert wird, die nicht bedeutet, dass es das gleiche ist wie eine virtual
Methode in der Klasse deklariert.
anstelle von virtuellen, unter der Annahme, dass Methoden in der Schnittstelle standardmäßig abstrakt ist, macht mehr Sinn. –
Ja, das ist in Ordnung, aber sobald der Compiler virtuell an die Methode anknüpft und Sie bei der Implementierung der Methode wieder virtuell setzen, sollte Compiler sagen, dass Sie die ursprüngliche Deklaration verbergen. –