Интерфейсы - какой смысл? - PullRequest
241 голосов
/ 23 июля 2011

Причина интерфейсов действительно ускользает от меня.Насколько я понимаю, это своего рода обходной путь для несуществующего мульти-наследования, которого нет в C # (или мне так сказали).

Все, что я вижу, это то, что вы предопределите некоторых членови функции, которые затем должны быть заново определены в классе.Таким образом, делая интерфейс избыточным.Это просто похоже на синтаксис ... ну, чушь для меня.базовый класс Pizza вместо интерфейса.

простой пример (взят из другого вклада переполнения стека)

public interface IPizza
{
    public void Order();
}

public class PepperoniPizza : IPizza
{
    public void Order()
    {
        //Order Pepperoni pizza
    }
}

public class HawaiiPizza : IPizza
{
    public void Order()
    {
        //Order HawaiiPizza
    }
}

Ответы [ 28 ]

1 голос
/ 20 ноября 2016

Здесь есть много хороших ответов, но я хотел бы попробовать с небольшой точки зрения.

Возможно, вы знакомы с принципами SOLID объектно-ориентированного проектирования. В итоге:

S - Принцип единой ответственности O - Открытый / Закрытый Принцип L - принцип замещения Лискова I - Принцип разделения интерфейса D - Принцип обращения зависимостей

Следование принципам SOLID помогает создавать код, который будет чистым, хорошо продуманным, связным и слабо связанным. Учитывая, что:

«Управление зависимостями является ключевой проблемой в программном обеспечении в любом масштабе» (Дональд Кнут)

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

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

0 голосов
/ 23 июля 2011

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

0 голосов
/ 23 июля 2011

Можно задать действительно замечательные примеры.

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

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

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

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

0 голосов
/ 27 мая 2014

Интерфейсы также могут быть последовательно соединены для создания еще одного интерфейса.Эта возможность реализации нескольких интерфейсов дает разработчику преимущество добавления функциональности в их классы без необходимости изменения функциональности текущего класса (Принципы SOLID)

O = "Классы должны быть открыты для расширения, но закрыты для модификации"

0 голосов
/ 23 мая 2014

Я разделяю ваше чувство, что интерфейсы не нужны.Вот цитата из Cwalina, стр. 80 Framework Design Guidelines «Я часто здесь говорю, что интерфейсы определяют контракты. Я считаю, что это опасный миф. Сами по себе интерфейсы не определяют много. ...» Он и соавтор Абрамс управляли 3 релизами.Net для Microsoft.Далее он говорит, что «контракт» «выражен» в реализации класса.ИМХО, наблюдая за этим в течение десятилетий, многие люди предупреждали Microsoft, что доведение инженерной парадигмы до максимума в OLE / COM может показаться хорошим, но ее полезность больше связана с аппаратным обеспечением.Особенно в 80-х и 90-х годах, когда кодификации стали взаимодействовать.В нашем мире Интернета по TCP / IP мало ценится аппаратная и программная гимнастика, через которую мы прыгнули бы, чтобы получить решения, «подключенные» между мейнфреймами, мини-компьютерами и микропроцессорами, в которых ПК составляли лишь незначительное меньшинство.Таким образом, кодирование интерфейсов и их протоколов сделало вычислительную работу.И интерфейсы правили.Но что общего между решением вопроса о том, как заставить X.25 работать с вашим приложением, и публикацией рецептов на праздники?Я много лет кодирую C ++ и C # и никогда не создавал их один раз.

0 голосов
/ 18 января 2014

Правильно ли я тогда еще раз взглянуть на интерфейсы, графический интерфейс (winforms / WPF) похож на интерфейс.Он отображает только то, с чем будет взаимодействовать конечный пользователь.Тогда конечному пользователю не нужно будет знать, что входит в дизайн приложения, но он будет знать, что он может с ним сделать, основываясь на доступных параметрах в форме.В представлении ООП идея состоит в том, чтобы создать структурированный интерфейс, который информирует других пользователей о ваших, например, библиотеках DLL, о том, что доступно для использования, и что это как гарантия / контракт, что поле, методы и свойства будут доступны для использования (наследуютсяклассы).

0 голосов
/ 03 сентября 2018

Для меня преимущество / преимущество интерфейса в том, что он более гибкий, чем абстрактный класс.Поскольку вы можете наследовать только 1 абстрактный класс, но можете реализовать несколько интерфейсов, изменения в системе, которая наследует абстрактный класс во многих местах, становятся проблематичными.Если оно унаследовано в 100 местах, изменение требует изменений для всех 100. Но с помощью интерфейса вы можете поместить новое изменение в новый интерфейс и просто использовать этот интерфейс там, где это необходимо (Interface Seq. Из SOLID).Кроме того, использование памяти выглядит так, как если бы интерфейс был меньше, поскольку объект в примере интерфейса используется только один раз в памяти, несмотря на то, сколько мест реализует интерфейс.

0 голосов
/ 24 июля 2011

Самый простой способ думать об интерфейсах - это распознать, что означает наследование. Если класс CC наследует класс C, это означает, что:

  1. Класс CC может использовать любые открытые или защищенные члены класса C, как если бы они были его собственными, и, таким образом, ему нужно только реализовать вещи, которых нет в родительском классе.
  2. Ссылка на CC может быть передана или присвоена подпрограмме или переменной, которая ожидает ссылку на C.

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

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

Одна приятная особенность этого (недостаточно используемая в .net framework, IMHO) заключается в том, что они позволяют декларативно указывать, что может делать объект. Некоторым объектам, например, понадобится объект источника данных, из которого они могут извлекать вещи по индексу (как это возможно в List), но им не нужно ничего там хранить. Другие подпрограммы будут нуждаться в объекте хранилища данных, где они могут хранить вещи не по индексу (как в Collection.Add), но им не нужно будет что-либо читать обратно. Некоторые типы данных разрешают доступ по индексу, но не разрешают запись; другие позволят писать, но не разрешат доступ по индексу. Некоторые, конечно, позволят и то и другое.

Если бы ReadableByIndex и Appendable были несвязанными базовыми классами, было бы невозможно определить тип, который можно было бы передать как вещам, ожидающим ReadableByIndex, так и вещам, ожидающим Appendable. Можно попытаться смягчить это, используя ReadableByIndex или Appendable, производные от другого; производный класс должен был бы сделать доступными открытые члены для обеих целей, но предупредите, что некоторые открытые члены могут фактически не работать. Некоторые из классов и интерфейсов Microsoft делают это, но это довольно странно. Более чистый подход состоит в том, чтобы иметь интерфейсы для различных целей, а затем объекты должны реализовывать интерфейсы для того, что они действительно могут делать. Если бы у одного был интерфейс IReadableByIndex, а у другого интерфейса IAppendable, классы, которые могли бы делать один или другой, могли бы реализовать соответствующие интерфейсы для вещей, которые они могут делать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...