Кога да използваме абстрактен клас срещу интерфейс в C #

Когато проектирате приложения, е важно да знаете кога да използвате абстрактен клас и кога да използвате интерфейс. Въпреки че абстрактните класове и интерфейси изглеждат сходни в някои отношения, има ключови разлики, които ще определят кой е най-добрият избор за това, което се опитвате да постигнете. В тази публикация в блога ще обсъдя тези разлики и как да реша кога да използвам коя.

Кратък отговор: Абстрактният клас ви позволява да създадете функционалност, която подкласовете могат да внедрят или отменят. Интерфейсът ви позволява само да дефинирате функционалност, а не да я прилагате. И докато клас може да разшири само един абстрактен клас, той може да се възползва от множество интерфейси. 

C # абстрактен клас обяснен

Абстрактният клас е специален тип клас, който не може да бъде създаден. Абстрактният клас е проектиран да бъде наследен от подкласове, които внедряват или заменят неговите методи. С други думи, абстрактните класове са или частично внедрени, или изобщо не са приложени. Можете да имате функционалност във вашия абстрактен клас - методите в абстрактния клас могат да бъдат както абстрактни, така и конкретни. Абстрактният клас може да има конструктори - това е една основна разлика между абстрактния клас и интерфейса. Можете да се възползвате от абстрактните класове за проектиране на компоненти и да посочите някакво ниво на обща функционалност, която трябва да бъде внедрена от производни класове.

C # интерфейс обяснен

Интерфейсът по същество е договор - той няма никакво изпълнение. Интерфейсът може да съдържа само декларации на методи; не може да съдържа дефиниции на методи. Нито можете да имате данни за членове в интерфейс. Докато абстрактният клас може да съдържа дефиниции на методи, полета и конструктори, интерфейсът може да има само декларации за събития, методи и свойства. Методите, декларирани в интерфейс, трябва да бъдат внедрени от класовете, които реализират интерфейса. Имайте предвид, че клас може да реализира повече от един интерфейс, но да разшири само един клас. Класът, който реализира интерфейса, трябва да реализира всички свои членове. Подобно на абстрактния клас, интерфейсът не може да бъде създаден.

Трябва ли да използвам абстрактен клас или интерфейс?

Абстрактните класове ви предоставят гъвкавостта да имате определени конкретни методи и някои други методи, които производните класове трябва да прилагат. За разлика от това, ако използвате интерфейси, ще трябва да внедрите всички методи в класа, който разширява интерфейса. Абстрактният клас е добър избор, ако имате планове за бъдещо разширяване - т.е. ако е вероятно бъдещо разширяване в йерархията на класовете. Ако искате да предоставите поддръжка за бъдещо разширяване при използване на интерфейси, ще трябва да разширите интерфейса и да създадете нов.

При различна бележка е лесно да добавите нов интерфейс към йерархията, ако е необходимо. Ако обаче вече имате абстрактен клас във вашата йерархия, не можете да добавите друг - т.е. можете да добавите абстрактен клас само ако няма наличен. Трябва да използвате интерфейс, ако искате договор за някакво поведение или функционалност. Не трябва да използвате интерфейс, ако трябва да напишете същия код за интерфейсните методи. В този случай трябва да използвате абстрактен клас, да дефинирате метода веднъж и да го използвате повторно, ако е необходимо. Използвайте интерфейси, за да отделите кода на приложението си от конкретни негови реализации или да ограничите достъпа до членове от определен тип.

Както се посочва в документацията на Microsoft за интерфейси:

Използвайки интерфейси, можете например да включите поведение от множество източници в клас. Тази способност е важна в C #, защото езикът не поддържа множествено наследяване на класове. Освен това трябва да използвате интерфейс, ако искате да симулирате наследяване за структури, защото те всъщност не могат да наследят от друга структура или клас.

Неявни и явни реализации на интерфейса

Интерфейсите могат да бъдат внедрени имплицитно или изрично. Позволете ми да обясня как се различават тези две реализации. Помислете за интерфейс, наречен IBusinessLogic.

публичен интерфейс IBusinessLogic

{

   void Initialize ();

}

Следният клас с име BusinessLogicреализира IBusinessLogicинтерфейса.

публична класа BusinessLogic: IBusinessLogic

{

   public void Initialize ()

   {

       // Някакъв код

   }

}

Можете да създадете екземпляр на BusinessLogicкласа изрично и след това да извикате Initialize()метода, както е показано по-долу.

 IBusinessLogic businessLogic = нов BusinessLogic ();

businessLogic.Initialize ();

Следният кодов фрагмент илюстрира как можете да внедрите IBusinessLogicинтерфейса имплицитно.

публична класа BusinessLogic: IBusinessLogic

{

   void IBusinessLogic.Initialize ()

   {

   }

}

Вече можете да извикате Initialize()метода по същия начин, като използвате препратка към IBusinessLogicинтерфейса. Разликата в двата подхода е, че когато внедрите интерфейса изрично във вашия клас, вие сте ограничени да извиквате метод на вашия интерфейс, използвайки препратка само към интерфейса. Следователно следният кодов фрагмент няма да работи, т.е. няма да се компилира.

 BusinessLogic businessLogic = нов BusinessLogic ();

businessLogic.Initialize ();

Как да направите повече в C #:

  • Кога да се използва абстрактен клас срещу интерфейс в C #
  • Как да работя с AutoMapper в C #
  • Как да използвам ламбда изрази в C #
  • Как да работя с Action, Func и Predicate делегати в C #
  • Как да работя с делегати в C #
  • Как да внедрите прост регистратор в C #
  • Как да работя с атрибути в C #
  • Как да работя с log4net в C #
  • Как да приложим шаблона за проектиране на хранилището в C #
  • Как да работя с отражение в C #
  • Как да работя с файлова система за наблюдение в C #
  • Как да извършите мързелива инициализация в C #
  • Как да работите с MSMQ в C #
  • Как да работя с методи за разширение в C #
  • Как да използваме ламбда изрази в C #
  • Кога да се използва летливата ключова дума в C #
  • Как да използвам ключовата дума yield в C #
  • Как да приложим полиморфизъм в C #
  • Как да изградите свой собствен планировчик на задачи в C #
  • Как да работя с RabbitMQ в C #
  • Как да работите с кортеж в C #
  • Проучване на виртуални и абстрактни методи в C #