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

При разработке приложений важно знать, когда использовать абстрактный класс, а когда - интерфейс. Хотя абстрактные классы и интерфейсы кажутся в некотором роде похожими, существуют ключевые различия, которые определяют, какой из них лучше всего подходит для того, что вы пытаетесь достичь. В этом сообщении блога я расскажу об этих различиях и о том, как решить, когда их использовать.

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

Объяснение абстрактного класса C #

Абстрактный класс - это особый тип класса, который не может быть создан. Абстрактный класс предназначен для наследования подклассами, которые либо реализуют, либо переопределяют его методы. Другими словами, абстрактные классы либо частично реализованы, либо не реализованы вовсе. Вы можете иметь функциональные возможности в своем абстрактном классе - методы в абстрактном классе могут быть как абстрактными, так и конкретными. Абстрактный класс может иметь конструкторы - это одно из основных различий между абстрактным классом и интерфейсом. Вы можете воспользоваться преимуществами абстрактных классов для разработки компонентов и определения некоторого уровня общих функций, которые должны быть реализованы производными классами.

Объяснение интерфейса C #

Интерфейс - это, по сути, контракт - у него нет никакой реализации. Интерфейс может содержать только объявления методов; он не может содержать определения методов. У вас также не может быть никаких данных о членах в интерфейсе. В то время как абстрактный класс может содержать определения методов, поля и конструкторы, интерфейс может иметь только объявления событий, методов и свойств. Методы, объявленные в интерфейсе, должны быть реализованы классами, реализующими интерфейс. Обратите внимание, что класс может реализовывать более одного интерфейса, но расширять только один класс. Класс, реализующий интерфейс, должен реализовывать все его члены. Подобно абстрактному классу, интерфейс не может быть создан.

Должен ли я использовать абстрактный класс или интерфейс?

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

С другой стороны, при необходимости легко добавить новый интерфейс в иерархию. Однако, если у вас уже есть абстрактный класс в вашей иерархии, вы не можете добавить еще один, т. Е. Вы можете добавить абстрактный класс, только если он недоступен. Вам следует использовать интерфейс, если вы хотите заключить контракт на какое-то поведение или функциональность. Вы не должны использовать интерфейс, если вам нужно написать тот же код для методов интерфейса. В этом случае вы должны использовать абстрактный класс, определить метод один раз и повторно использовать его по мере необходимости. Используйте интерфейсы для отделения кода вашего приложения от его конкретных реализаций или для ограничения доступа к членам определенного типа.

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

Используя интерфейсы, вы можете, например, включить в класс поведение из нескольких источников. Эта возможность важна для C #, потому что язык не поддерживает множественное наследование классов. Кроме того, вы должны использовать интерфейс, если хотите имитировать наследование для структур, потому что они не могут наследовать от другой структуры или класса.

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

Интерфейсы могут быть реализованы неявно или явно. Позвольте мне объяснить, чем отличаются эти две реализации. Рассмотрим интерфейс с именем IBusinessLogic.

открытый интерфейс IBusinessLogic

{

   void Initialize ();

}

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

открытый класс BusinessLogic: IBusinessLogic

{

   public void Initialize ()

   {

       // Какой-то код

   }

}

Вы можете создать экземпляр BusinessLogicкласса явно, а затем вызвать Initialize()метод, как показано ниже.

 IBusinessLogic businessLogic = new 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 #
  • Как работать с filesystemwatcher на C #
  • Как выполнить ленивую инициализацию в C #
  • Как работать с MSMQ на C #
  • Как работать с методами расширения в C #
  • Как использовать лямбда-выражения в C #
  • Когда использовать ключевое слово volatile в C #
  • Как использовать ключевое слово yield в C #
  • Как реализовать полиморфизм в C #
  • Как создать собственный планировщик задач на C #
  • Как работать с RabbitMQ на C #
  • Как работать с кортежем на C #
  • Изучение виртуальных и абстрактных методов в C #