2010-12-17 11 views
11

Ich habe eine spezifische Abfrage mit den Schnittstellen. Standardmäßig sind Interface-Methoden abstrakt und virtuell. Wenn wir also diese Schnittstelle implementieren und eine Definition in der Klasse angeben, überschreiben wir diese Methode, aber wenn wir die Methode in der implementierenden Klasse erneut als virtuell markieren, denkt der Compiler nicht darüber nach, ob wir das wirklich versuchen um die ursprüngliche virtuelle Schnittstellenmethode auszublenden.Wenn wir eine virtuelle Methode in der Basisklasse haben und die abgeleitete Klasse die Methode wieder als virtuell markiert hat, gibt der Compiler die Warnung, dass Sie die Basisklassenmethode verstecken, also neue verwenden, wenn Sie absichtlich sind die Basisklassenmethode ausblenden.Warum ist virtuell erlaubt während der Implementierung der Schnittstellenmethoden?

public interface ITestInterface 
{ 
void virtualmethod(); // this method is by default virtual. 
} 

public class TestInterface :ITestInterface 
{ 
public virtual void virtualmethod() 
{ 
// Now compiler should consider that i am actually hiding the interface virtual method. 
} 
} 

, wenn Sie den obigen Code für die Schnittstelle und offen in ILDASM bauen Sie den Code wie folgt sehen: .method public hidebysig newslot abstract virtual instance void virtualmethod() cil managed { }//end of method ITestInterface::virtualmethod

+2

anstelle von virtuellen, unter der Annahme, dass Methoden in der Schnittstelle standardmäßig abstrakt ist, macht mehr Sinn. –

+0

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. –

Antwort

39

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.

+0

Bitte überprüfen Sie die Frage erneut, wie ich den IL-Code für die gleiche hinzugefügt –

+0

.method öffentlichen hidebysig Newslot abstrakte virtuelle Instanz void virtualmethod() cil verwaltete {} // Ende der Methode ITestInterface :: virtualmethod –

2

Schnittstelle ist keine Basisklasse, daher werden Implementierungsmethoden nicht überschrieben. Die Schnittstelle deklariert nur die Methoden, Interface-Methoden sind standardmäßig nicht virtuell, infact-Interfaces deklarieren nur die Methoden, die in der Klasse verfügbar sind, die diese Schnittstelle implementiert.

Deklaration kann nicht virtuell sein.

Die Implementierung kann oder kann nicht virtuell sein und ist vollständig von der Logik des Implementierers abhängig.

+0

Schnittstellen sind nur ein Typ mit dem virtuellen Methoden so das Verhalten sollte gleich wie Klassen sein. –

+1

@Mohit - Das ist nicht ganz richtig. Ja, sie sind nur ein anderer Typ, aber sie sind ein * Interface * Typ, der den Unterschied macht. Schnittstellen und Klassen sind auf IL-Ebene unterschiedlich. –

Verwandte Themen