MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Implementarea interfețelor în clase de bază și derivate

Dacă o clasă implementează o interfață, acea clasă trebuie să implementeze toate metodele și proprietățile interfeței care nu au o implementare implicită. Totuși, metodele pot fi făcute abstracte, lăsând implementarea acestora pentru clasele derivate:

interface IMovable
{
   void Move();
}
abstract class Person : IMovable
{
   public abstract void Move();
}
class Driver : Person
{
   public override void Move() => Console.WriteLine("Șoferul conduce mașina");
}

La implementarea interfeței, sunt luate în considerare și metodele și proprietățile moștenite din clasa de bază. De exemplu:

IAction action = new HeroAction();
action.Move();  // Move in BaseAction

interface IAction
{
   void Move();
}
class BaseAction
{
   public void Move() => Console.WriteLine("Move in BaseAction");
}
class HeroAction : BaseAction, IAction { }

Aici, clasa HeroAction implementează interfața IAction, însă pentru implementarea metodei Move din interfață este folosită metoda Move moștenită din clasa de bază BaseAction. Astfel, clasa HeroAction nu este obligată să implementeze metoda Move, deoarece aceasta este deja definită în clasa de bază BaseAction.

Trebuie menționat că, dacă o clasă moștenește o altă clasă și implementează o interfață, cum este cazul clasei HeroAction, numele clasei de bază trebuie să fie menționat înaintea interfețelor implementate:

class HeroAction : BaseAction, IAction { }

Modificarea implementării interfețelor în clase derivate

Poate apărea situația în care clasa de bază a implementat interfața, dar în clasa derivată este necesar să se schimbe implementarea acestei interfețe. Ce se poate face în acest caz? Putem folosi fie suprascrierea, fie ascunderea metodei sau proprietății interfeței.

Prima variantă - suprascrierea metodelor virtuale/abstracte:

interface IAction
{
   void Move();
}
class BaseAction : IAction
{
   public virtual void Move() => Console.WriteLine("Move in BaseAction");
}
class HeroAction : BaseAction
{
   public override void Move() => Console.WriteLine("Move in HeroAction");
}

În clasa de bază BaseAction, metoda implementată a interfeței este definită ca virtuală (ar putea fi și abstractă), iar în clasa derivată este suprascrisă.

La apelarea metodei prin intermediul unei variabile de interfață, dacă aceasta se referă la un obiect al clasei derivate, se va folosi implementarea din clasa derivată:

BaseAction action1 = new HeroAction();
action1.Move();            // Move in HeroAction

IAction action2 = new HeroAction();
action2.Move();            // Move in HeroAction

A doua variantă - ascunderea metodei în clasa derivată:

interface IAction
{
   void Move();
}
class BaseAction : IAction
{
   public void Move() => Console.WriteLine("Move in BaseAction");
}
class HeroAction : BaseAction
{
   public new void Move() => Console.WriteLine("Move in HeroAction");
}

Utilizăm aceste clase:

BaseAction action1 = new HeroAction();
action1.Move();            // Move in BaseAction

IAction action2 = new HeroAction();
action2.Move();            // Move in BaseAction

Deoarece interfața este implementată în clasa BaseAction, prin variabila action2 se poate accesa doar implementarea metodei Move din clasa de bază BaseAction.

A treia variantă - reimplementarea interfeței în clasa derivată:

interface IAction
{
   void Move();
}
class BaseAction : IAction
{
   public void Move() => Console.WriteLine("Move in BaseAction");
}
class HeroAction : BaseAction, IAction
{
   public new void Move() => Console.WriteLine("Move in HeroAction");
}

În acest caz, implementarea metodei din clasa de bază va fi ignorată:

BaseAction action1 = new HeroAction();
action1.Move();            // Move in BaseAction

IAction action2 = new HeroAction();
action2.Move();            // Move in HeroAction

HeroAction action3 = new HeroAction();
action3.Move();            // Move in HeroAction

De asemenea, trebuie menționat că, în cazul variabilei action1, se aplică în continuare legarea timpurie, prin care se poate apela doar implementarea metodei Move din clasa de bază, pe care această variabilă o reprezintă.

A patra variantă: implementarea explicită a interfeței:

interface IAction
{
   void Move();
}
class BaseAction : IAction
{
   public void Move() => Console.WriteLine("Move in BaseAction");
}
class HeroAction : BaseAction, IAction
{
   public new void Move() => Console.WriteLine("Move in HeroAction");
   // implementarea explicită a interfeței
   void IAction.Move() => Console.WriteLine("Move in IAction");
}

În acest caz, pentru variabila IAction va fi utilizată implementarea explicită a interfeței IAction, iar pentru variabila HeroAction se va utiliza în continuare implementarea implicită:

BaseAction action1 = new HeroAction();
action1.Move();            // Move in BaseAction

IAction action2 = new HeroAction();
action2.Move();            // Move in IAction

HeroAction action3 = new HeroAction();
action3.Move();            // Move in HeroAction
← Lecția anterioară Lecția următoare →