Абстрактный класс или интерфейс?

Чем они отличаются между собой и в чём отличия?
В плане синтаксиса, интерфейс может содержать внутри себя только методы без реализации, свойства, события. В то время как абстрактный класс поддерживает функционал любого другого класса(поля, реализованные методы, делегаты, события, свойства, конструкторы...), но запрещает создавать экземпляры своего типа. Также нужно помнить, что C# не поддерживает множественное наследование и, соответственно, унаследоваться от нескольких классов не получиться, а вот от нескольких интерфейсов - да.

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

Вот пару советов по определению нужного механизма:

  • Связь потомка с предком. Любой тип может наследовать только одну реализацию. Если производный тип не может ограничиваться отношением типа «является частным случаем» с базовым типом, нужно применять интерфейс, а не базовый тип. Интерфейс подразумевает отношение «поддерживает функциональность». Например, тип может преобразовывать экземпляры самого себя в другой тип (IConvertible), может создать набор экземпляров самого себя (ISerializable) и т. д. Заметьте, что значимые типы должны наследовать от типа System.ValueType и поэтому не могут наследовать от произвольного базового класса. В этом случае нужно определять интерфейс.
  • Простота использования. Разработчику проще определить новый тип, производный от базового, чем создать интерфейс. Базовый тип может предоставлять массу функций, и в производном типе потребуется внести лишь незначительные изменения, чтобы изменить его поведение. При создании интерфейса в новом типе придется реализовывать все члены.
  • Четкая реализация. Как бы хорошо ни был документирован контракт, вряд ли будет реализован абсолютно корректно. По сути, проблемы COM связаны именно с этим — вот почему некоторые COM-объекты нормально работают только с Microsoft Word или Microsoft Internet Explorer. Базовый тип с хорошей реализацией основных функций — прекрасная отправная точка, вам останется изменить лишь отдельные части.
  • Управление версиями. Когда вы добавляете метод к базовому типу, производный тип наследует стандартную реализацию этого метода без всяких затрат. Пользовательский исходный код даже не нужно перекомпилировать. Добавление нового члена к интерфейсу требует изменения пользовательского исходного кода и его перекомпиляции.

Наконец, нужно сказать, что на самом деле можно определить интерфейс и создать базовый класс, который реализует интерфейс. Например, в FCL определен интерфейс IComparer<T>, и любой тип может реализовать этот интерфейс. Кроме того, FCL предоставляет абстрактный базовый класс Comparer<T>, который реализует этот интерфейс (абстрактно) и предлагает реализацию по умолчанию для необобщенного метода Compare интерфейса IComparer. Применение обеих возможностей дает большую гибкость, поскольку разработчики теперь могут выбрать из двух вариантов наиболее предпочтительный.

results matching ""

    No results matching ""