Generics

in C#, Informatica, Programmazione

Interfacce custom e generics

Nell’articolo precedente abbiamo introdotto i generics.  In questo nuovo articolo introduciamo le interfacce generiche.

Nulla di particolarmente complesso, è sufficiente definire nel modo tradizionale l’interfaccia, indicando però un parametro generico:

public interface ICounter<T>
{
}

Allo stesso modo è possibile indicare il valore di ritorno che dovrà essere sovrascritto:

public interface ICounter<T>
{
    int Count { get; }
    T Get(int index);
}

Ovviamente, come per l’utilizzo di interfacce “tipizzate”, è possibile sfruttare l’ereditarietà:

public interface ICounter<T>
{
    int Count { get; }
    T Get(int index);
}

public interface IPersons<T> : ICounter<T>
{
    void Add(T item);
}

Implementare un’interfaccia generica

Le classi che implementano un’interfaccia generica devono sottostare alle specifiche definite all’interno dell’interfaccia stessa.

public interface ICounter<T>
{
    int Count { get; }
    T Get(int index);
}

public interface IPersons<T> : ICounter<T>
{
    void Add(T item);
}

public class People<T> : IPersons<T>
{
  ...
}

Ovviamente dovranno essere implementati TUTTI i metodi specificati all’interno delle interfacce.

Passare un’interfaccia generica come parametro

Un’interfaccia generica è a tutti gli effetti un’interfaccia: possiamo quindi utilizzarla come parametro di un metodo. Supponiamo, ad esempio, di aver definito un’interfaccia che rappresenta una forma geometrica:

public interface IShapes<T>
{
    int Count { get; }
    void Add(T item);
    T Get(int index);
}

Allo stesso modo definiamo un’interfaccia per un oggetto di tipo “Round” :

public interface IRound
{
    string Name { get; }
    double Radius { get; set; }
    double Diameter { get; }
    double Circumference { get; }
    double Area { get; }
}

A questo punto procediamo con l’implementazione della classe Circle (che implementa l’oggetto IRound:

public class Circle : IRound
{
    ...
    ...
}

A questo punto, da un’ ipotetica di una classe è possibile utilizzare un’interfaccia come parametro di un metodo, nel seguente modo:

public void ShowShapes(IShapes<IRound> shps)
    {
        for (int i = 0; i < shps.Count; i++)
        {
            IRound rnd = shps.Get(i);

            Console.WriteLine("================================");
            Console.WriteLine("{0} Characteristics", rnd.Name);
            Console.WriteLine("--------------------------------");
            Console.WriteLine("Radius:        {0}", rnd.Radius);
            Console.WriteLine("Diameter:      {0}", rnd.Diameter);
            Console.WriteLine("Circumference: {0}", rnd.Circumference);
            Console.WriteLine("Area:          {0}", rnd.Area);
        }
        Console.WriteLine("===============================");
    }

Restituire un’interfaccia generica come parametro

E’ possibile restituire un’interfaccia generica da un metodo nel seguente modo:

public IShapes<IRound> GetShapes()
{
    ...
}

Ovviamente il tipo ritornato deve soddisfare tutte le regole definite all’interno dell’interfaccia.