03/10/26 · 5 min de lectura

Interfaces en C#

Cómo crear interfaces e implementarlas en clases.

Imagen por Jez Timms .

Las interfaces pueden considerarse un contrato sobre la funcionalidad.

Cualquier clase que implementa una interfaz debe tener todos sus métodos y propiedades. En cambio, la clase que se implementa puede tratarse como la interfaz por otra clase, usando el polimorfismo ..

Es importante tener en cuenta que las interfaces no son clases y no pueden tener sus propias instancias. Mientras que la herencia es una relación, donde una clase hereda de otra, las interfaces usan una relación de implementación, en donde una clase implementa una interfaz.

class A {  // Class base }

class B : A { // inherits from A }

/*...*/

interface IA {  // interface base }

class B : IA { // implements from IA }

Las interfaces se declaran usualmente fuera de una clase. Cuando se declara las interfaces generalmente usarías un script por interfaz. Pero para este ejemplo, vamos a mostrar dos en el mismo script.

Por convención, las interfaces se declaran usando un nombre que empieza con una I mayúscula seguido de un nombre que empieza con otra letra mayúscula. Desde que las interfaces normalmente describen algún tipo de funcional que las clases que se implementan tendrán, muchas de las interfaces terminan en el sufijo -able. Sin embargo, vale la pena tomar en cuenta que esto no es mandatorio y podría ser desorientador, dependiendo de la interfaz.

public interface IKillable { // I ... -able }
public interface IDamageable { // I ... -able }

Hemos declarado dos interfaces aquí, IKillable, IDamageable. En IKillable tenemos una función llamada Kill(), la misma que tiene un tipo de retorno void y no tiene parámetros.

public interface IKillable
{
    void Kill();
}

Cualquier clase que implementa la interfaz IKillable debe tener una función pública que coincida con esta firma.

public class SomeClass : IKillable
{
    public void Kill()
    {
        // implementación en una clase
    }
}

La interfaz IDamageable tiene un tipo genérico T. Esto significa que cualquier cosa en la interfaz puede tener un tipo genérico. La función que tenemos en IDamageable, Damage(), toma un parámetro tipo T.

public interface IDamageable
{
    void Damage(T damageTaken);
}

Cuando una clase implementa una interfaz con un tipo genérico, el tipo debe escogerse. Luego, el tipo correspondiente debe usarse a través de toda la clase.

public class SomeClass : IDamageable<float>
{
    public void Damage(float damageTaken)
    {
        // implementación en una clase
        // con tipo de dato concreto
    }
}

Implementar una interfaz viene con algunos requisitos y algunos beneficios.

Para implementar un interfaz, una clase debe declarar públicamente todos los métodos, propiedades, eventos e indexadores que existan en esta interfaz. El no hacerlo resultará en un error.

La mejor ventaja de las interfaces es que te permiten definir funcionalidades comunes a lo largo de muchas clases. Por lo tanto, puedes hacer suposiciones acertadas sobre lo que las clases pueden hacer basado en las interfaces que implementan.

Para implementar una interfaz, simplemente agrega una coma después de cualquier herencia que la clase tenga seguida del nombre de la interfaz. Si la clase no hereda, entonces no se requiere la coma. Si la interfaz tiene un tipo genérico; entonces, el nombre debe seguirse de corchetes angulares con el tipo dentro de ellos.

En este caso tenemos la clase Avatar la misma que hereda de MonoBehaviour e implementa IKillable e IDamageable con el tipo float. También debemos declarar ambas funciones que se requieren para estas interfaces. Ten en cuenta que el cuerpo de las funciones es independiente de las interfaces y pueden implementarse como gustes. Estas fuentes de interfaces podrían ser útiles si hubiera una situación en tu juego donde quieras dañar o destruir todo. Simplemente al encontrar todo lo que implementa IKillable o IDamageable podrías asegurarte de que tendrían las funciones Kill() o Damage().

public class Avatar : MonoBehaviour, IKillable, IDamageable<float>
{
    // the required method of the IKillable interface
    public void Kill()
    {
        // do something fun
    }
    // the required method of the IDamageable interface
    public void Damage(float damageTaken)
    {
        // do something fun
    }
}

Tal vez te estés preguntando por qué implementamos una interfaz en una clase, cuando podrías simplemente definir en una función que está en una clase y que otras funciones hereden de ella.

La respuesta más fácil es que puedes implementar interfaces múltiples, pero no puedes heredar de clases múltiples. Por lo tanto, las interfaces son una manera muy fácil de proveer un gran rango de funcionalidad. Una respuesta más adecuada es que las interfaces se usan para definir la funcionalidad común a lo largo de muchas clases que no están relacionadas entre sí.

Toma en consideración dos clases: Wall y Car. Wall y Car tienen casi nada en común entre sí, excepto que ambas se pueden dañar. ya que son tan diferentes entre sí, heredar de una clase base no tiene mucho sentido.

? => Wall ? => Car

Sin embargo, la implementación de una interfaz funciona muy bien.

IDamageable => Wall IDamageable => Car

Gist del proyecto

Apoya el contenido de mi blog a través de:

Fuente:

Copiado!