MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Interfețele în generice

Interfețele ca restricții pentru generice

Interfețele pot fi utilizate ca restricții pentru generice. Dacă pentru restricții se poate specifica doar o singură clasă, pentru interfețe se pot specifica mai multe.

Să presupunem că avem următoarele interfețe și o clasă care le implementează:

interface IMessage
{
   string Text { get; } // textul mesajului
}
interface IPrintable
{
   void Print();
}
class Message : IMessage, IPrintable
{
   public string Text { get; }
   public Message(string text) => Text = text;

   public void Print() => Console.WriteLine(Text);
}

Interfața IMessage reprezintă o interfață pentru mesaj și definește proprietatea Text pentru stocarea textului mesajului. Interfața IPrintable definește metoda Print pentru imprimarea condiționată a mesajului. Iar clasa Message implementează aceste interfețe.

Utilizăm interfețele enumerate mai sus ca restricții pentru o clasă generică:

class Messenger<T> where T: IMessage, IPrintable
{
   public void Send(T message)
   {
       Console.WriteLine("Trimiterea mesajului:");
       message.Print();
   }
}

În acest caz, clasa unui mesager condiționat folosește parametrul T - tipul care implementează atât interfața IMessage, cât și IPrintable. De exemplu, clasa Message definită mai sus implementează ambele interfețe, așa că putem folosi acest tip pentru a tipiza obiectele Messenger:

// creăm un mesager
var telegram = new Messenger<Message>();
// creăm un mesaj
var message = new Message("Hello World!");
// trimitem mesajul
telegram.Send(message);

De asemenea, parametrul T poate reprezenta o interfață care moștenește ambele interfețe:

interface IPrintableMessage: IPrintable, IMessage { }
class PrintableMessage : IPrintableMessage
{
   public string Text { get; }
   public PrintableMessage(string text) => Text = text;
   public void Print() => Console.WriteLine(Text);
}

În acest caz, putem tipiza obiectele Messenger cu tipul IPrintableMessage:

var telegram = new Messenger<IPrintableMessage>();
var message = new PrintableMessage("Hello World!");
telegram.Send(message);

Interfețe generice

La fel ca și clasele, interfețele pot fi generice:

interface IUser<T>
{
   T Id { get; }
}
class User<T> : IUser<T>
{
   public T Id { get; }
   public User(T id) => Id = id;
}

Interfața IUser este tipizată cu parametrul T, care este folosit la implementarea interfeței în clasa User. Variabila _id este definită ca T, permițând astfel utilizarea diverselor tipuri pentru id.

Definim două implementări: una care folosește tipul int ca parametru și alta care folosește tipul string:

IUser<int> user1 = new User<int>(6789);
Console.WriteLine(user1.Id);    // 6789

IUser<string> user2 = new User<string>("12345");
Console.WriteLine(user2.Id);    // 12345

De asemenea, la implementarea interfeței putem specifica explicit ce tip va fi folosit pentru parametrul T:

class IntUser : IUser<int>
{
   public int Id { get; }
   public IntUser(int id) => Id = id;
}

Utilizare:

IUser<int> user1 = new IntUser(2345);
Console.WriteLine(user1.Id);    // 2345

IntUser user2 = new IntUser(9840);
Console.WriteLine(user2.Id);    // 9840
← Lecția anterioară Lecția următoare →