Las interfaces en .NET y otros lenguajes son una manera de establecer un contrato entre dos clases, de manera que dejemos perfectamente definido de qué manera vana poder interactuar entre ellas. Así, si una clase implementa una determinada interfaz sabemos que dicha clase va a disponer de determinados métodos y podemos contar con ellos a la hora de trabajar con ésta. Además gracias a las interfaces podemos implementar ciertos tipos de polimorfismo o genericidad a la hora de trabajar con conjuntos de clases que implementan la misma interfaz.

En fin, nada nuevo en el párrafo anterior para un programador mínimamente experimentado de .NET o cualquier otro lenguaje orientado a objetos. En nuestro curso de preparación del examen 70-536 se trata profusamente este tema, como es lógico. Lo interesante, y objeto de este post, viene a la hora de decidir cómo implementar una determinada interfaz en una clase. Así, si tenemos definida una interfaz cualquiera, por ejemplo esta:

public interface IMiInterfaz
{
	void MiMetodo();
}

Tenemos dos formas de implementarla en una clase. La primera de ellas es la manera implícita:

public class PruebaInterfazImplicita : IMiInterfaz
{
	public void MiMetodo()
	{
		Console.WriteLine("Hola");
	}
}

La otra manera es la explícita, en la que indicamos de manera evidente qué interfaz estamos implementando:

public class PruebaInterfazExplicita : IMiInterfaz
{
	void IMiInterfaz.MiMetodo()
	{
		Console.WriteLine("Hola");
	}
}

F√≠jate que en este caso ponemos el nombre de la interfaz delante del m√©todo para indicar a qu√© interfaz pertenece √©ste, y adem√°s el m√©todo no es p√ļblico.

Generalmente los programadores no le damos importancia a la forma en la que se implementa una interfaz y se usan indistintamente ambas formas, pero ¬Ņrealmente existe alguna diferencia?

Pues sí, hay diferencias y son importantes. A continuación resumiré los detalles relacionados con la implementación de interfaces y con qué cosas debemos tener cuidado.

1.- Implementación de varias interfaces

En .NET no existe la herencia m√ļltiple de clases. Algunos alegar√°n que es una carencia, y otros dir√°n que es incluso una ventaja. Se ha escrito mucho sobre el tema. Lo que s√≠ est√° permitido es la implementaci√≥n de diversas interfaces. As√≠, si tenemos dos interfaces que definen m√©todos con el mismo nombre ¬Ņc√≥mo distinguimos unos de otros?. Por ejemplo, si tenemos dos interfaces I1 e I2 as√≠:

public interface I1
{
	void M();
}

public interface I2
{
	void M();
}

public class PruebaDobleInterfaz : I1, I2
{
	public void M()
	{
		Console.WriteLine("Método M");
	}
}


public class Prueba
{
	public static void Main()
	{
		PruebaDobleInterfaz obj = new PruebaDobleInterfaz();
		obj.M();
		((I1) obj).M();
		((I2) obj).M();
		Console.Write("Pulsa una tecla para terminar...");
		Console.ReadKey();
	}
}

¬ŅCual ser√° el resultado del c√≥digo anterior? Pues que funcionar√° perfectamente y obtendremos el mismo texto tres veces, resultado de llamar al m√©todo M. Esto est√° genial si realmente queremos que la implementaci√≥n del m√©todo sea id√©ntica en ambos casos, pero al tratarse de interfaces diferentes generalmente no ser√° as√≠. Ah√≠ es donde entra la implementaci√≥n expl√≠cita, ya que indicaremos qu√© interfaz exactamente estamos implementando y no habr√° confusi√≥n posible. Si ahora definimos la clase as√≠:

public class PruebaDobleInterfaz : I1, I2
{
	public void M()
	{
		Console.WriteLine("Método M");
	}
	
	void I1.M()
	{
		Console.WriteLine("Método I1.M");
	}
	
	void I2.M()
	{
		Console.WriteLine("Método I2.M");
	}
}

Pues ahora el código anterior mostrará tres mensajes diferentes, dependiendo de si llamamos al método M en la clase, o en una interfaz específica.

2.- Ocultar la implementación de miembros de interfaces

Al implementar de manera explícita miembros de interfaces lo que conseguimos es ocultarlos frente a su uso directo en la clase. Por ejemplo:

public interface IMiInterfaz
{
	void MiMetodo();
}

public class PruebaInterfazImplicita : IMiInterfaz
{
	void IMiInterfaz.MiMetodo()
	{
		Console.WriteLine("Hola");
	}
}

public class Prueba
{
	public static void Main()
	{
		PruebaInterfazImplicita obj = new PruebaInterfazImplicita();
		//obj.MiMetodo(); //Produce un error de compilación de que la clase no contiene ese método
		((IMiInterfaz) obj).MiMetodo();
		Console.Write("Pulsa una tecla para terminar...");
		Console.ReadKey();
	}
}

Fíjate que ahora la llamada al método implementado explícitamente falla cuando lo intentamos hace directamente desde la clase, y se requiere el "casting" explícito a la interfaz para poder llamarlo. Además el método nose mostrará a los programadores en el Intellisense de Visual Studio, por lo que n tendrán la tentación de usarlo de cualquier manera, ocultándolo efectivamente.

¬ŅPara qu√© podr√≠a servir esto? Pues por ejemplo para ocultar ciertos miembros que queremos que se usen con cuidado y sabiendo lo que se hace. Por ejemplo, es muy t√≠pico hacer esto al utilizar la interfaz IDisposable, ocultando la implementaci√≥n del m√©todo Dispose() que debe ser llamado por el runtime y no generalmente por el programador.

3.- Ni p√ļblicos, ni virtuales ni abstractos

Los m√©todos de interfaces implementados de manera expl√≠cita no pueden definirse como p√ļblicos (se declaran autom√°ticamente como privados para ocultarlos) ni tampoco como abstractos o virtuales. Hay que tenerlo en cuenta por si lo necesit√°semos. Esto tiene dos importantes implicaciones:

1.- las clases que implementan interfaces de manera explicita no pueden ser abstractas.
2.- Las clases derivadas de clases que implementan interfaces de manera explícita no pueden sobrescribir los métodos definidos explícitamente.

Detalles adicionales

Si quieres ver algunos ejemplso m√°s de c√≥mo implementar interfaces expl√≠citamente puedes echarle un vistazo a este documento de MSDN (en espa√Īol): Tutorial de implementaci√≥n expl√≠cita de interfaces.

Si ya dominas el tema y quieres profundizar para conocer los detalles de bajo nivel de cómo se implementan por debajo ambas formas de declarar métodos de interfaces, te recomiento este excelente artículo sobre el asunto de Chris Brumme, ingeniero distinguido de Microsoft, aquí: "cbrumme's Weblog: Interface Layout". ¡Realmente interesante!

Espero que te haya resultado interesante, aunque sea algo √°rido :-)

💪🏻 ¬ŅEste post te ha ayudado?, ¬Ņhas aprendido algo nuevo?
Pues NO te pido que me invites a un café... Te pido algo más fácil y mucho mejor

Escrito por un humano, no por una IA