[C#] Зачем нужны интерфейсы?

6yrop

как бы вы ответили на такой вопрос?

Helga87

Для уменьшения зависимостей между частями приложения

6yrop

что такое "часть приложения"? сборки, классы?

Helga87

Пофигу. Главное, что одна часть может не знать, как реализована другая.

6yrop

такую фразу можно сказать даже о процедурном прогрммировании. Одна функция не знает как реализована другая функция. Там интерфейсов нет.

maggi14

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

alexkravchuk

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

6yrop

что значит в удобном? в удобном для чего?

6yrop

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

maggi14

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

maggi14

чтобы надежно заменять компоненты

6yrop

вообще-то тред про C#, там ни реестра, ни файлов с хедерами нет, там есть сборки.

aleks058

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

6yrop

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

maggi14

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

6yrop

или в шарпе вообще интерфейсы есть, а компоненты никто не ищет?
ну типа того. Во много похоже на Java, если что

aleks058



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

alexkravchuk

> вообще-то тред про C#
Не знаю, как с C#, но в Яве, afaik, интерфейсы придумали как альтернативу множественному наследованию в C++, для упрощения реализации и большей строгости, что-ли... Подозреваю, что в C# тоже самое.

maggi14

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

maggi14

а какая тут альтернатива множественному наследованию, если нельзя пользоваться готовыми методами?

6yrop

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

6yrop

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

6yrop

Я ответил на этот вопрос, исходя из свое опыта, так:
1. Интерфейсы используются когда, требуется, чтобы объект класса A мог быть представлен, как переменная типа IB, но не хочется использовать наследование классов, поскольку наследование классов дифицитная вещь -- может быть только один родитель. А если наследование классов уже есть, тогда интерфейс это единственный вариант.
2. В случае распределенного приложения (Remoting-а) интерфейс позволяет не держать всю серверную сборку на клиенте. Интерфейс определяется в общей сборке, которая лежит и на клиенте и на сервере.
Мне сказали, что это не полный ответ.............

bastii

В С#, можно рассматривать с точки зрения реализации: С# интерфейсами реализуется более общий полиморфизм (в отличии от расширения при использовании наследования когда один объект может вести себя как объект двух разных типов (в случае C# такие типы могут определяются только набором поддерживаемых операций, то что наз. интерфейсами) -- на уровне кода, вызовы через C# интерфейс реализованы специальным образом с дополнительным перенаправлением вызова, что дает возможность не зависеть размеру памяти, занимаемой объектом, который реализует множество интерфейсов. Если обходиться одним расширением, то такой вид полиморфизма можно реализовывать делегированием (пример такого подхода -- множественное наследование в С++ но при этом на каждый интерфейс +1 указатель как поле в структуре объекта.

Dasar

а где банальный ответ: интерфейсы нужны для реализации полиморфизма?

bastii

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

maggi14

то есть это не фича, а костыль?

bastii

фича, читай последний пост Даркгрея, я просто раскрыл детали

maggi14

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

bastii

Ок, финальная версия ответа:
Интерфейсы в C# для ЭФФЕКТИВНОЙ реализации полиморфизма В СЛУЧАЕ МНОЖЕСТВЕННЫХ ОТНОШЕНИЙ УТОЧНЕНИЯ НА ТИПАХ
детальнее см.
еще детальнее: была статья в MSDN Magazine, кажется Джефри Рихтера, про реализацию интерфейсов (называние не помню).

Dasar

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

6yrop

полиморфизм следует из того, что
объект класса A мог быть представлен, как переменная типа IB

Dasar

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

Dasar

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

6yrop

полиморфизм, как понятие, это разное поведение объекта в зависимости от типа объекта. Как таковой полиморфизм мне может и не нужен. Например, у нас уже есть две независимых иерархии, класс A из первой иерархии, класс B из второй. У нас есть метод
void f(IC c)
{
  c.g;
}
и мы хотим, чтобы он принимал объекты типа A и типа B. Реализация метода g требуется везде одинаковая (т.е. полиморфизм не нужен). Если бы не было иерархий, то проще унаследовать классы A и B, от базового
class IC
{
  public void g {} //не виртуальный
}
А если уже есть иерархии (или мы хотим оставить возможность иерархий то нам надо использовать интерфейс.

6yrop

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

Dasar

> Если бы не было иерархий, то проще унаследовать классы A и B, от базового
нет, конечно, не проще.
потому что, если у тебя еще есть метод (а в большой системе - так обычно и бывает который принимает:

void f(ID d)
{
d.g;
}

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

6yrop

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

Dasar

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

Dasar

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

bastii

ИМХО можно говорить только про интерфейсы C#, Java и т.д. Иначе придется долго соображать, что это такое. Если проецировать с С#, т.е. рассматривать интерфейс как требование со стороны клиента поддержки объектом определенного набора методов с определенным сигнатурами. То с общих позиций полиморфизма при развитой модели типов не понятно почему такой частный случай спецификации типа отдельно выделяют, называя его интерфейсом. Если скажем требовать чтобы метод getCount возвращал неотрицательное число, или чтобы метод add(object o) менял состояние объекта так, что getCount после вызова возвращал на 1 больше и т.д. Так можно дойти и до более конкретных требований, которые фактически определяют реализацию. С другой стороны, зачем требования на сигнатуры? Чтобы гарантировано вызов x.getCount не выкинул какое-то рантаим эксепшин, т.к. я использую результат как значение типа int, а мне вернули не int ? Ну и какая от этого польза в общем контексте (если у тебя, например, код упадет если вернет отрицательное число).
В таких языках как C# и Java все очень завязано на реализацию, где интерфейсами реализуют специальный вид полиморфизма, который на практике очень важен, и который необходимо эффективно реализовывать. Фактически просто нет других вариантов, как можно реализовывать такой множественный полиморфизм, которые давали бы сравнимую эффективность с точки зрения производительности, и дополнительно несли какие-то бонусы.

Dasar

> То с общих позиций полиморфизма при развитой модели типов не понятно почему такой частный случай спецификации типа отдельно выделяют, называя его интерфейсом
потому что когда закладывались основы этих языков - это было все что знали/исследовали о контрактах на тот момент.
на данный момент исследовали чуть больше - появились всякие ковариантности и т.д., что возможно будет реализовано в следующих языках в нормальном объеме.
> Так можно дойти и до более конкретных требований, которые фактически определяют реализацию.
тот же Eiffel именно такие требования и поддерживает, и при этом имеют свою нишу при разработке программ.
> С другой стороны, зачем требования на сигнатуры? Чтобы гарантировано вызов x.getCount не выкинул какое-то рантаим эксепшин
откуда ты выкопал какие-то гарантии?
сигнатуры лишь помогают вынести часть runtime-ошибок на уровень компиляции, и еще раз подчеркиваю - что ничего не гарантируют.

bastii

А в Eiffel интерфейс как отдельное понятие присутствует?
Ладно, это я к тому, что нужно определиться с вопросом, есть варианты:
а) вопрос про интерфейсы C#, такие так они есть -- тогда вопрос "зачем они нужны", нужно рассматривать с точки зрения реализации;
б) вопрос про то, как интерфейсами пользоваться в С# -- тогда вопрос "для чего они нужны" нужно рассматриваться с архитектурной точки зрения;
в) вопрос про интерфейсы вообще, в общем контексте ООП -- тогда тут надо начинать философствовать на тему полиморфизма и т.д.

bastii

откуда ты выкопал какие-то гарантии?
Ты же сам рассматриваешь интерфейс как какой-то контракт, на который может рассчитывать клиент. Ну, так общими словами: гарантии как элементы контракта (мб слово не самое удачное подобрал).

Dasar

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

Dasar

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

bastii

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

bastii

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

Dasar

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

bastii

Там это тоже декларируется.
Each method of a remote interface, an interface that extends java.rmi.Remote, must list RemoteException in its throws clause.

Dasar

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

bastii

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

6yrop

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

что ты хотел сказать приведенным кодом, я не понял. Речь идет о возможности C# explicit interface member implementations?

bleyman

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

6yrop

о чем и речь, это сложнее, чем просто унаследовать

koly

flood.programming at forum.local

6yrop

на сомом деле вопрос был отнюдь не флудовой, это народ начал флудить
Переформулирую вопрос:
1. В каких случаях следует применять интерфейсы?
2. Какие преимущества дают интерфейсы в тех случаях, когда есть другие варианты решения проблемы?
Речь идет о написании кода на языке C#.

Dasar

> 1. В каких случаях следует применять интерфейсы?
1. При разработке разными людьми кода класса и кода его использования
2. для тех случаях, когда сложно сказать - как именно и где именно будет реализовываться данных функционал
 (как пример - ICollection, заранее сложно сказать - где именно и как именно функционал стоящий за ICollection будет реализовываться)
3. При разделение кода на крупные независимые единицы

Dasar

> 2. Какие преимущества дают интерфейсы в тех случаях, когда есть другие варианты решения проблемы?
большую независимость.
быстрее (по крайней мере для .net 1.1 чем делегаты
Оставить комментарий
Имя или ник:
Комментарий: