La implementación explícita de interfaces en .NET es una característica del lenguaje (no solamente de .NET) que, aunque es poco conocida, puede ser útil en muchos casos.

Normalmente todo el mundo implementa los interfaces de manera implícita, ya que es a lo que nos hemos acostumbrado y vemos normalmente en la mayoría de ejemplos programación con interfaces, pero eso no quiere decir que sea la única manera de hacerlo, ni que sea la mejor, ya que eso depende siempre del caso.

El tipo de implementación que vayamos a utilizar en ningún caso condiciona la manera en que creamos la interfaz, ya que cualquier interfaz puede ser implementada tanto implícitamente como explícitamente.

En este artículo vamos a ver qué es, cómo se hace, y además, os daré un proyecto con unos cuantos ejemplos para que lo veáis funcionando!

Cómo se implementa un interfaz explícitamente

Vamos a ver cómo implementaríamos un interfaz explícitamente en nuestras clases.

Primero definimos un interfaz como cualquier otro que hayamos hecho antes

public interface ITest
{
    string TestMethod();
}

La implementación implícita, a la que todos estamos acostumbrados, sería algo parecido a esto:

public class MiClaseImplicita : ITest
{
    public string TestMethod()
    {
        // Aquí hago cosas....
    }
}

Pero en nuestro caso, haremos una  implementación explicita, que sería algo así:

public class MiClaseExplicita : ITest
{
    string ITest.TestMethod()
    {
        // Aquí hago cosas...
    }
}

Como veis, no hay muchos cambios entre una implementación y la otra.

La diferencia es que hemos quitado el ámbito del método (public) y hemos colocado delante del nombre del método el nombre del interfaz. Aunque el cambio parece trivial, no lo es.

De esta manera, el método TestMethod ya no es un miembro de nuestra clase, sino que implementa directamente un miembro del interfaz ITest.

Diferencias entre implementación implícita y explícita

Cuando implementamos un método de forma explícita, el método ya no es un miembro de la clase, sino del interfaz que implementamos. Ésto quiere decir que no es accesible por otros métodos de la clase ni desde una instancia de la clase, sino que necesitamos acceder a ellos desde una instancia de la interfaz.

Con lo cual, ésto sería correcto:

MiClaseImplicita obj = new MiClaseImplicita();
string a = obj.TestMethod();

pero ESTO NO:

MiClaseExplicita obj = new MiClaseExplicita();
string a = obj.TestMethod();

En éste segundo caso, obtendríamos un error de compilación, ya que TestMethod() no es miembro de la clase MiClaseExplicita, sino de ITest, con lo cual, la manera correcta de acceder a ese método sería la siguiente:

ITest obj = new MiClaseExplicita();
string a = obj.TestMethod();

Casos de uso

Bien, la siguiente pregunta que os debe venir a la mente es… ¿ para qué me sirve ?

Las respuestas pueden ser varias. Aquí os dejo algunas, pero seguro que se os ocurren algunas más:

  • Desambiguación entre interfaces cuando tienen métodos con la misma firma.
  • Ocultación de detalles del interfaz que no necesita el usuario de la clase.

Desambiguación de interfaces

A veces, dos interfaces pueden contener métodos con la misma firma, y nos interesan implementaciones distintas para cada uno de ellos.

Por ejemplo:

interface IMovie { string GetTitle(); }
interface ISerie { string GetTitle(); }

public class Episode : IMovie, ISerie
{
    private string _title;
    private int _season;
    private int _episode;
    private string _episodeTitle;

    public Episode(string title, int season, int episode, string episodeTitle)
    {
        _title = title;
        _season = season;
        _episode = episode;
        _episodeTitle = episodeTitle;
    }

    // Implement IMovie
    string IMovie.GetTitle()
    {
        return _title;
    }

    // Implement ISerie
    string ISerie.GetTitle()
    {
        return string.Format("{0} - (S{1:00}/E{2:00}) {3}", 
              _title, _season, _episode, _episodeTitle);
    }

}

Esta implementación de la clase Episode nos permitiría sacar el título general de la serie si lo tratamos como una película:

var serieObj = new Episode("The Walking Dead", 5, 10, "No Sanctuary");
Console.WriteLine(((IMovie)serieObj).GetTitle());

Daría como resultado: The Walking Dead

Pero también nos permitiría obtener el título con el número de episodio cuando lo tratásemos como un episodio de la serie:

Console.WriteLine(((ISerie)serieObj).GetTitle());

Daría como resultado: The Walking Dead – (S05/E10) No Sanctuary

Ocultación de la implementación

Otro motivo de la implementación explicita de una interfaz sería la ocultación de la implementación del interfaz a los desarrolladores que vayan a utilizar la clase. En este caso, el interfaz IDisposable es necesario para hacer limpieza, pero nadie tiene por qué verlo.
Si lo implementamos explícitamente, solamente al utilizar nuestro objeto como IDisposable, será visible el método.

interface IDisposable
{
    void Dispose();
}

class MyFile : IDisposable
{
    void IDisposable.Dispose()
    {
        Close();
    }

    public void Close()
    {
        // Do what's necessary to close the file
        System.GC.SuppressFinalize(this);
    }
}

Ejemplos

Para que podaís verlo en funcionamiento y hacer vuestras pruebas, he creado un pequeño proyecto y lo he subido a mi repositorio público de código en BitBucket.

Podéis obtenerlo clonando el repositorio con Git usando la dirección:

https://bitbucket.org/joanvilarino/explicitinterfacedemo.git

O también podéis bajar el archivo ZIP directamente del repositorio usando este enlace a los archivos ZIP.

Gracias por leer el artículo! Nos vemos en el próximo…

Follow me

Joan Vilariño

Senior .NET Developer at Ohpen
Follow me