Bienvenidos a otro post sobre programación orientada a objetos.
Hoy veremos que es una interfaz el cual está directamente relacionado con la herencia, ya que como explicamos en el post de la herencia, una clase puede heredar o implementar tantas interfaces como necesite.
Índice
1 - Qué es una interfaz en programación orientada a objetos
Una interfaz es un contrato entre dos entidades, esto quiere decir que una interfaz provee un servicio a una clase consumidora. Por ende, la interfaz solo nos muestra la declaración de los métodos que esta posee, no su implementación, permitiendo así su encapsulamiento.
Aunque esta regla de utilizar únicamente la cabecera del método en la interfaz puede verse afectada en C#8, como ya vimos en el avance, ya que va a permitir añadir cuerpo en la declaración en las interfaces, pero por ahora, no se puede
Una interfaz se define utilizando la palabra reservada “interfaz”. Y por norma general, indicamos en el nombre que es una interfaz haciendo empezar el nombre de la misma por la letra I mayúscula.
public interface IPieza
{
}
Las interfaces pueden contener los siguientes miembros:
- Métodos
- Propiedades
- Indexers
- Eventos
public interface IPieza
{
decimal Area();
decimal Perimetro();
}
Como vemos en el ejemplo, hemos declarado dos métodos.
2 – Implementación de una interfaz
Para implementar una interfaz, debemos declarar una clase o una strutura(struct) que herede de la interfaz, y entonces, implementar todos sus miembros.
Por ejemplo, creamos la clase cuadrado y heredamos de una interfaz, por lo que debemos implementar sus métodos. Por defecto lo podemos dejar en NotImplementedException()
public class Cuadrado : IPieza
{
public decimal Lado { get; private set; }
public Cuadrado(decimal lado)
{
Lado = lado;
}
public decimal Area()
{
return Lado * Lado;
}
public decimal Perimetro()
{
return Lado * 4;
}
}
Cuando implementamos una interfaz debemos de asegurar un par de puntos:
- Los métodos y tipos que devuelven deben coincidir tanto en la interfaz como en la clase.
- Deben ser los mismos parámetros
- Los métodos de la interfaz deben ser públicos
- La utilización de interfaces mejora el código y el rendimiento de la aplicación.
3 – Múltiples clases heredan de una interfaz
Uno de los casos más comunes en programación orientada a objetos es que tenemos varias clases que heredan de una interfaz, lo que implica que en ambas debemos implementar el código. Para ello creamos en el código la clase triangulo (rectángulo) conjunto a la anterior de cuadrado, ambas son piezas. Por lo que ambas heredan de IPieza.
public class TrianguloRectangulo : IPieza
{
public decimal LadoA { get; set; }
public decimal LadoB { get; set; }
public decimal Hipotenusa { get; set; }
public TrianguloRectangulo(decimal ladoa, decimal ladob)
{
LadoA = ladoa;
LadoB = ladob;
Hipotenusa = CalculateHipotenusa(ladoa, ladob);
}
private decimal CalculateHipotenusa(decimal ladoa, decimal ladob)
{
return Convert.ToDecimal(Math.Sqrt((double)(ladoa * ladoa + ladob * ladob)));
}
public decimal Area()
{
return LadoA * LadoB / 2;
}
public decimal Perimetro()
{
return LadoA + LadoB + Hipotenusa;
}
}
Como podemos observar en ambos casos tenemos el área y el perímetro.
Si recordamos de la herencia, las clases son también del tipo del que heredan, lo que quiere decir que ambas clases, tanto Cuadrado, como TrianguloRectangulo, las podemos convertir en IPieza:
IPieza cuadrado = new Cuadrado(5);
IPieza trianguloRectangulo = new TrianguloRectangulo(5, 3);
Console.WriteLine($"El área del cuadrado es {cuadrado.Area()}");
Console.WriteLine($"El perímetro del cuadrado es {cuadrado.Perimetro()}");
Console.WriteLine($"El área del triángulo es {trianguloRectangulo.Area()}");
Console.WriteLine($"El perímetro del triángulo es {trianguloRectangulo.Perimetro()}");
//Resultado :
El área del cuadrado es 25
El perímetro del cuadrado es 20
El área del triángulo es 7.5
El perímetro del triángulo es 13.8309518948453
Este ejemplo es muy sencillito, pero imaginarios una lista con más de un millón de piezas, y cada una con diferentes formas, al heredar todas de IPieza, nos permite tener un bucle con únicamente una línea, un bucle foreach que ejecute el método Area() si lo que queremos es mostrar el área.
El uso de interfaces facilita enormemente programar cuando pasamos entidades reales a código.
Por supuesto se pueden tener métodos adicionales, normalmente privados, dentro de la clase, pero ellos no serán accesibles a través de la interfaz.
4 – Múltiples interfaces para en una sola clase
Puede darse el caso de que necesitemos implementar mas de una interfaz en nuestra clase, para ello no hay ningún problema simplemente las separamos con comas.
Pero esas interfaces pueden contener un método con el mismo nombre el mismo valor de retorno y los mismos parámetros.
La forma que tendremos entonces para diferenciar uno del otro es, en la implementación dentro de la clase
public interface interfaz1
{
void MetodoRepetido();
}
public interface interfaz2
{
void MetodoRepetido();
}
public class EjemploRepeticionMetodo : interfaz1, interfaz2
{
public EjemploRepeticionMetodo()
{
}
void interfaz1.MetodoRepetido()
{
throw new NotImplementedException();
}
void interfaz2.MetodoRepetido()
{
throw new NotImplementedException();
}
}
Como podemos observar no utilizamos un modificador de acceso en la implementación del método.