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.
en lugar de virtual, asumiendo que los métodos en la interfaz son abstractos por defecto, tiene más sentido. –
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. –