Tabla de Contenido
0. Introducción1. Colisión de Miembros: Métodos
2. Ejemplo Extendido de Resolución de Colisión de Métodos
3. Nota Especial
4. Conclusiones
5. Glosario
6. Enlaces & Literatura
0. Introducción
Otro de los términos interesantes en la composición y uso de interfaces consiste en hacer explícita su implementación en las clases o structs. Vamos a explorar la manera de implementar métodos de interfaces de forma explícita en clases o structs concretos. Ya veremos que esto nos va a resultar útil cuando tengamos métodos que colisionen por poseer un identificador igual a otro en interfaces diferentes.
1. Colisión de Miembros: Métodos
Ya en la primera parte -crf. Interfaces en C# - Parte 1- aprendimos que una clase o struct puede implementar una o varias interfaces. Recórdemoslo para el caso de las clases:
[public] interface {nombre de la interfaz} : {nombre de la interfaz} [,...]
La convención sintáctica [,...] indica un listado de interfaces opcionales a implementar. Dado que la extensión de una interfaz puede incluir una o más interfaces.
Ahora asumamos (de manera abstracta) que tenemos dos interfaces con identificadores de métodos homónimos. Así:
public interface Interfaz1
{
void Metodo();
}
public interface Interface2
{
int Metodo();
}
Ahora una clase que implemente ambas interfaces:
public class ClaseConcreata : Interfaz1, Interfaz2
{
// ¿Qué pasa si hacemos esto?:
public void Metodo()
{
// Implementación;
}
int Metodo()
{
return 0;
}
}
Veamos lo que ocurre en tiempo de compilación: > Prueba de compilación.
Se genera el error CS0111 [4]:
error CS0111: A member `ClaseConcreta.Metodo()' is already defined. Rename this member or use different parameter types
En resumen, el segundo método es homónimo, y no es una versión sobrecargada.
Para resolver este problema, implementamos de forma explícita los miembros de la interfaz (cualquiera de las dos anterior: Interfaz1 o Interfaz2). Eso lo logramos del siguiente modo:
public class ClaseConcreata : Interfaz1, Interfaz2
{
// ¿Qué pasa si hacemos esto?:
public void Metodo()
{
// Implementación;
}
int Interfaz2.Metodo()
{
return 0;
}
}
Ahora la compilación es satisfactoria. Sólo fue necesario especificar el nombre de la clase junto con el método a implementar, separados por el operador punto (.).
Vale hacer una aclaración respecto al método explícitamente declarado:
int Interfaz2.Metodo()
A esto también hay que agregar, que para acceder al método explícitamente implementado ya no es posible hacerlo a través de la instancia de la clase que implementa las interfaces (como en el caso anterior: ClaseConcreta : Interfaz1, Interfaz2).
2. Ejemplo Extendido de Resolución de Colisión de Métodos
En este ejemplo vamos a comprender cómo resolver la colisión de métodos en un caso práctico y simple. Éste consiste en obtener las medidas de un objeto cuadrado tridimensional (una caja, concretamente) en dos sistemas de unidades: el sistema inglés, y el SI (Sistema Internacional).
Archivo ISistemaInglesMedidas.cs:
Obsérvese que en la implementación de la clase Caja se explicita la implementación de los métodos de las interfaces que implementa Caja:
- Interfaz ISistemaInglesMedidas:
- double ISistemaInglesMedidas.Ancho()
- double ISistemaInglesMedidas.Largo()
- Interfaz ISistemaInternalMedidas:
- double ISistemaInternalMedidas.Ancho()
- double ISistemaInternalMedidas.Largo()
Debemos tener en cuenta que cuando realizamos una implementación explícita de un método de una interfaz, se omite el modificador de acceso.
Otro de los puntos nuevos e interesantes, ocurre en el cuerpo del método Main de la clase Caja:
- En la línea 53 se hace una conversión explícita de la instancia c (tipo Caja) a una referencia -sistemaIngles- de tipo ISistemaInglesMedidas.
- En la línea 53 se hace una conversión explícita de la instancia c (tipo Caja) a una referencia -sistemaIngles- de tipo ISistemaInternalMedidas.
Esto es necesario debido a la razón dada al final de la sección anterior: debemos invocar los métodos explícitamente implementados usando una instancia de la interfaz a la que pertenece el método abstracto.
Otro forma de alcanzar los resultados anteriores es:
Console.WriteLine("Ancho (pulgadas): {0}", ((ISistemaInglesMedidas)c).Ancho());
Console.WriteLine("Largo (pulgadas): {0}", ((ISistemaInglesMedidas)c).Largo());
Console.WriteLine("Ancho (cm): {0}", ((ISistemaInternalMedidas)c).Ancho());
Console.WriteLine("Largo (cm): {0}", ((ISistemaInternalMedidas)c).Largo());
Hemos utilizado la conversión explícita in situ e invocar los métodos correspondientes de las interfaces.
> Prueba de ejecución.
Resultado:
Ancho (pulgadas): 20 Largo (pulgadas): 30 Ancho (cm): 50.8 Largo (cm): 76.2
3. Nota Especial
En uno nos advierten acerca de otra de las razones que justifica el uso de métodos explícitamente implementados:
Figura 1. Razón para utilziar métodos explícitamente implementados. |
Conclusiones
Entendimos que la utilidad de los métodos explícitamente implementados permite remove el problema de colisión de miembros homónimos (i.e., métodos abstractos que tienen el mismo identificador (firma en general) en dos interfaces distintas). El ejemplo de sistemas medidas demostró la utilidad a través de presentación de valores de medidas de una caja (cuadrado) en el sistema inglés y el Sistema Internacional.
Glosario
- Clase
- Clase abstracta
- Clase concreata
- Implementación explícita
- Interfaz
- Modificador de acceso
Enlaces & Literatura
[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.[2]: Interfaces en C# - Parte 1 | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/05/interfaces-en-c-parte-1.html
[3]: Explicit Interface Implementation Tutorial (C#) - http://msdn.microsoft.com/en-us/library/aa288461%28v=vs.71%29.aspx
[4]: Compiler Error CS0111 - http://msdn.microsoft.com/en-us/library/ddza5cw4%28v=vs.90%29.aspx
J
No hay comentarios:
Publicar un comentario
Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.