Необходимость интерфейсов в C#

Что нужно для интерфейсов в C#? как мы пишем абстрактный метод в интерфейсах. вместо этого мы можем напрямую реализовать эти методы в классе.

12 ответов

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

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

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

Вы можете прочитать о полиморфизме.

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

Кроме того, вы можете реализовать несколько интерфейсов, но наследовать только один абстрактный класс. Я считаю это очень полезным, потому что мои бизнес-объекты имеют лучшее представление.

При написании любого приложения N-Tiered, которое отделяет бизнес-логику от презентации, я думаю, вы начнете находить много применений для интерфейсов.

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

Например:

1) попытаться, без интерфейса, раскрыть часть функциональности, реализованной в сборке "А", сборке "В", при этом фактическая реализация не будет видна сборке "А".

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

Интерфейс - это контракт, который определяет сигнатуру функциональности. Поэтому, если класс реализует интерфейс, он говорит внешнему миру, что он обеспечивает определенное поведение.

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

Если вы хотите написать тестируемый код, вам обычно нужно использовать интерфейсы. При модульном тестировании у вас может быть ClassA, который зависит от ClassB, который зависит от ClassC и т. Д., Но вы хотите только протестировать ClassA. Вы, конечно, не хотите создавать ClassC для передачи в ClassB просто для создания экземпляра ClassA.

В этом случае вы заставляете ClassA зависеть от IClassB (или более общего имени, скорее всего, ничего не говорящего о реализации ClassB) и макетировать IClassB в своих тестах.

Это все для управления зависимостями для меня.

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

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

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

Интерфейсы используются для определения поведения / свойств классов без указания реализации. Если вы начинаете думать о классах как о выполняющих роли, а не просто как о наборе методов и свойств, тогда вы можете начать присваивать классам несколько ролей, используя интерфейсы, что невозможно при использовании прямого наследования в C#, поскольку вы можете наследовать только от одного класса. Заставляя клиентов классов зависеть от интерфейсов (ролей), а не от самого класса, ваш код будет более слабо связан и, вероятно, лучше спроектирован.

Еще одним преимуществом этого является то, что если вы пишете модульные тесты, они, скорее всего, будут сосредоточены на поведении, а не на состоянии. Кодирование на основе интерфейсов позволяет очень легко создавать реализации макетов / заглушек для этого типа тестирования.

Не всем понадобятся интерфейсы - но большинство вещей с поведением, вероятно, (то есть, больше, чем просто набор данных) должны иметь их IMHO, так как у вас всегда будет две реализации: реальная в вашем приложении и одна или несколько фальшивых в ваших тестах,

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

Думайте об интерфейсах как о контрактах.

Вы создаете контракт, которому должен следовать класс. Например, если наш объект Dog должен иметь метод Walk, его определяющий класс должен реализовать этот метод.

Чтобы заставить каждый класс собаки (унаследованный или нет) реализовать этот метод, вы должны заставить их придерживаться контракта, то есть назначить интерфейс, который определяет этот метод.

Интерфейс - это конструкция, которая заставляет определенные классы следовать строгим правилам реализации.

Причина этого заключается в том, что в итоге вы получаете объекты Dog (унаследованные или нет), которые теперь по умолчанию имеют метод Walk. Это означает, что вы можете передавать эти объекты как параметры, будучи уверенными в том, что вы можете вызывать метод Walk для любого класса Dog (унаследованного или нет), и он будет обязательно реализован.

Согласно представленному GoF 1-му принципу: программа для интерфейса не является реализацией.

Это помогает во многих отношениях. Проще изменить реализацию, проще сделать код тестируемым и так далее...

Надеется, что это помогает.

Другие вопросы по тегам