MySQL Java JavaScript PHP Python HTML-CSS C-sharp C++ Go

Interfețe

Interfața reprezintă un tip de referință care poate defini o anumită funcționalitate - un set de metode și proprietăți fără implementare. Apoi această funcționalitate este implementată de clase și structuri care aplică aceste interfețe.

Definirea interfeței

Pentru definirea unei interfețe se folosește cuvântul cheie interface. De obicei, denumirile interfețelor în C# încep cu litera mare I, de exemplu, IComparable, IEnumerable (așa-numita notație maghiară), însă acesta nu este un cerință obligatorie, ci mai mult un stil de programare.

Ce poate defini o interfață? În general, interfețele pot defini următoarele entități:

  • Metode
  • Proprietăți
  • Indexatori
  • Evenimente
  • Câmpuri și constante statice (începând cu versiunea C# 8.0)

Cu toate acestea, interfețele nu pot defini variabile nestatice. De exemplu, o interfață simplă care definește toate aceste componente:

interface IMovable
{
   // constantă
   const int minSpeed = 0;     // viteza minimă
   // variabilă statică
   static int maxSpeed = 60;   // viteza maximă
   // metodă
   void Move();                // mișcare
   // proprietate
   string Name { get; set; }   // denumire
   
   delegate void MoveHandler(string message);  // definirea delegatului pentru eveniment
   // eveniment
   event MoveHandler MoveEvent;    // evenimentul de mișcare
}

În acest caz, este definită interfața IMovable, care reprezintă un obiect mobil. Această interfață conține diverse componente care descriu capabilitățile obiectului mobil. Adică, interfața descrie o anumită funcționalitate care ar trebui să existe la un obiect mobil.

Metodele și proprietățile interfeței pot să nu aibă implementare, în acest aspect se aseamănă cu metodele și proprietățile abstracte ale claselor abstracte. În acest caz, interfața definește metoda Move, care va reprezenta o anumită deplasare. Aceasta nu are implementare, nu acceptă niciun parametru și nu returnează nimic.

Același lucru este valabil și pentru proprietatea Name. La prima vedere, aceasta pare a fi o proprietate automată. Dar, în realitate, aceasta este o definiție a unei proprietăți într-o interfață, care nu are implementare, nu o proprietate automată.

Modificatori de acces

Un alt aspect în declararea unei interfețe: dacă membrii săi - metodele și proprietățile - nu au modificatori de acces, atunci de fapt, implicit, accesul este public, deoarece scopul interfeței este definirea funcționalității pentru implementarea ei de către o clasă.

Acest lucru se aplică și constantelor și variabilelor statice, care în clase și structuri, implicit, au modificatorul private. În interfețe, acestea au implicit modificatorul public. De exemplu, am putea accesa constanta minSpeed și variabila maxSpeed a interfeței IMovable:

Console.WriteLine(IMovable.maxSpeed);   // 60
Console.WriteLine(IMovable.minSpeed);   // 0

Dar, de asemenea, începând cu versiunea C# 8.0, putem specifica explicit modificatorii de acces ai componentelor interfeței:

interface IMovable
{
   public const int minSpeed = 0;     // viteza minimă
   private static int maxSpeed = 60;   // viteza maximă
   public void Move();
   protected internal string Name { get; set; }    // denumire
   public delegate void MoveHandler(string message);  // definirea delegatului pentru eveniment
   public event MoveHandler MoveEvent;    // evenimentul de mișcare
}

La fel ca și clasele, interfețele implicit au nivelul de acces internal, adică o astfel de interfață este accesibilă doar în cadrul proiectului curent. Dar cu ajutorul modificatorului public putem face interfața accesibilă public:

public interface IMovable
{
   void Move();
}

Implementarea implicită

De asemenea, începând cu versiunea C# 8.0, interfețele suportă implementarea implicită a metodelor și proprietăților. Aceasta înseamnă că putem defini în interfețe metode și proprietăți complete, care au implementare ca în clasele și structurile obișnuite. De exemplu, să definim implementarea implicită a metodei Move:

interface IMovable
{
   // implementarea implicită a metodei
   void Move()
   {
       Console.WriteLine("Walking");
   }
}

Cu implementarea implicită a proprietăților în interfețe este puțin mai complicat, deoarece nu putem defini variabile nestatice în interfețe, astfel încât în proprietățile interfeței nu putem manipula starea obiectului. Totuși, putem defini și implementarea implicită pentru proprietăți:

interface IMovable
{
   // implementarea implicită a metodei
   void Move() => Console.WriteLine("Walking");
   // implementarea implicită a proprietății
   // proprietate doar pentru citire
   int MaxSpeed { get { return 0; } }
}

Este de remarcat că, dacă interfața are metode și proprietăți private (adică cu modificatorul private), acestea trebuie să aibă implementare implicită. Același lucru se aplică și metodelor statice (nu neapărat private):

Console.WriteLine(IMovable.MaxSpeed);   // 60
IMovable.MaxSpeed = 65;
Console.WriteLine(IMovable.MaxSpeed);   // 65
double time = IMovable.GetTime(500, 10);
Console.WriteLine(time);    // 50

interface IMovable
{
   public const int minSpeed = 0;     // viteza minimă
   private static int maxSpeed = 60;   // viteza maximă
   // calculăm timpul necesar pentru a parcurge distanța distance cu viteza speed
   static double GetTime(double distance, double speed) => distance / speed;
   static int MaxSpeed
   {
       get => maxSpeed;
       set
       {
           if (value > 0) maxSpeed = value;
       }
   }
}

Adăugarea unei interfețe

Este de menționat că în Visual Studio există un component special pentru adăugarea unei noi interfețe într-un fișier separat. Pentru a adăuga o interfață în proiect, putem face click dreapta pe proiect și în meniul contextual care apare, selectăm Add -> New Item... și în fereastra de dialog pentru adăugarea unui nou component selectăm opțiunea Interface:

Deși putem adăuga, de asemenea, un fișier standard de clasă sau orice alt fișier de cod C# și în el să definim interfața.