2010-12-17 15 views
11

Tengo una consulta específica con las interfaces. Por defecto, los métodos de interfaz son abstractos y virtuales, así que si implementamos esa interfaz y damos definición en la clase, de hecho reemplazamos ese método, pero cuando marcamos el método como virtual nuevamente en la clase implementadora, ¿por qué el compilador no está considerando que realmente lo estamos intentando? para ocultar el método virtual de la interfaz original. Como si tuviéramos un método virtual en la clase base y la clase derivada marcó de nuevo el método como virtual, en ese caso el compilador le advierte que está ocultando el método de la clase base, por lo que debe usar nuevo si está intencionalmente ocultando el método de la clase base.¿por qué se permite virtual al implementar los métodos de interfaz?

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

si se genera el código anterior para la interfaz y abierta en ILDASM verá el código como el siguiente: .method public hidebysig newslot abstract virtual instance void virtualmethod() cil managed { }//end of method ITestInterface::virtualmethod

+2

en lugar de virtual, asumiendo que los métodos en la interfaz son abstractos por defecto, tiene más sentido. –

+0

sí, bien, pero una vez que el compilador se conecta virtual con el método y vuelve a ponerlo virtual mientras implementa el método, el compilador debería decir que está ocultando la declaración original. –

Respuesta

39

métodos que se implementan desde una interfaz son no virtual por defecto. Simplemente está proporcionando una implementación del contrato definido en la definición de la interfaz. Al marcar el método como virtual, está permitiendo que las clases derivadas proporcionen una implementación adicional o separada a la vez que se respeta el contrato según lo definido.

Considere este ejemplo:

interface IAnimal 
{ 
    string Speak(); 
} 

class Dog : IAnimal 
{ 
    public string Speak() 
    { 
     return "Bark!"; 
    } 
} 

La clase Dog es implementación de la interfaz, proporcionando una implementación del contrato IAnimal. No hay métodos virtuales aquí y no hay anulación.

Ahora consideremos el siguiente ejemplo:

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(); 
    } 
} 

Ahora la clase Dog ha declarado Speak ser virtual que permite que las clases derivadas para proporcionar una implementación adicional o nuevo. Esto no rompe el contrato con IAnimal ya que cualquier llamada al método Speak aún devuelve una cadena.

Ok, un último ejemplo. Recuerde que las interfaces no requieren una implementación, solo requieren que el contrato esté satisfecho. Esto significa que a la interfaz solo le preocupa que exista un miembro en la clase de implementación que tenga una firma coincidente. Esto significa que también podríamos hacer esto: todavía

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"; 
    } 
} 

Aviso ahora que la clase Dog proporciona ninguna implementación en absoluto para Speak ha cumplido con los requisitos del contrato.

Interfaces también se heredan de una clase a otra por lo que en todos los ejemplos anteriores tanto Dog y GoldenRetriever implementar la interfaz IAnimal. Ni clase ocultar el método Speak - ambas clases implementar it.


Bueno, creo que su confusión puede provenir del hecho de que el método virtual se define en una interfaz, no en una clase.Aquí está la IL para la interfaz I definida anteriormente:

.class private interface abstract auto ansi IAnimal 
{ 
    .method public hidebysig newslot abstract 
     virtual instance string Speak() cil managed 
    { 
    } 
} 

Mientras está en lo cierto que el método se define como virtual también hay que notar que el tipo que aquí se designa como un interface. Esto es puramente un detalle de implementación del MSIL generado por el compilador C# de Microsoft; otro compilador podría generar fácilmente código diferente siempre y cuando proporcionara semánticamente el mismo resultado.

Lo importante aquí es esto: aunque el método está declarado como virtual en la interfaz, eso no significa que sea lo mismo que un método virtual declarado en clase.

+0

Por favor, compruebe la pregunta nuevamente ya que agregué el código IL para el mismo –

+0

.method public hidebysig newslot extracto virtual instancia void virtualmethod() cil managed {} // fin del método ITestInterface :: virtualmethod –

2

La interfaz no es Clase base, por lo que los métodos de implementación no se anulan. La interfaz solo declara los métodos. Los métodos de interfaz no son virtuales por defecto, de hecho las interfaces solo declaran los métodos que están disponibles en la clase que implementa esa interfaz.

La declaración no puede ser virtual.

La implementación puede o no ser virtual, que es completamente dependiente de la lógica del implementador.

+0

Las interfaces son solo un tipo con el virtual métodos para que el comportamiento sea el mismo que para las clases. –

+1

@Mohit - Esto no es del todo cierto. Sí, son simplemente otro tipo pero son un tipo de * interfaz * que marca la diferencia. Las interfaces y las clases son diferentes en el nivel IL. –

Cuestiones relacionadas