| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Общие вопросы по .NET и C# > Интерфейсы, в чем суть ? отличия от подмешиваний |
| Автор: fell 29.8.2012, 10:20 |
| Всем привет Итак для чего используются интерфейсы. Например для решения такой задачи - использовать 2 разных метода в двух разных классах. class A method AA class B method BB Создав класс С мы можем наследоваться только либо от класса А либо от класса B, а хотелось бы сразу от двух, чтобы использовать методы AA и BB. Для этого есть интерфейсы, создаем интерфейсы interface A method AA interface B method BB Однако далее следует непонятный момент. В интерфейсах мы фактически определяем только названия и сигнатуры методов и имплиментируем их уже в классе, а хотелось бы использовать полностью имплементированные методы. Эта задача хорошо решается в руби, используя подмешивания. Module A method AA Module B method BB class A include A include B method AA method BB Вопрос в чем суть интерфейсов тогда ? получается что они не равнозначны подмешиваниям и в данном случае подмешивания лучше справляются с задачей, чем интерфейс. |
| Автор: diadiavova 29.8.2012, 22:40 |
Подмешивания - это что-то типа такого? http://msdn.microsoft.com/ru-ru/library/bb383977%28VS.100%29.aspx Если бы это делалось для того, чтобы использовать методы, то по всей видимости в интерфейсах была бы возможна реализация методов. Раз там этого нет, то очевидно же, что предназначены они не для этого. В первую очередь благодаря им пишется полиморфный код. Смысл как раз в том и есть, что с объектами всех типов, реализующих один интерфейс, можно работать единообразным способом, то есть у них гарантированно будут реализованы все члены задекларированные в интерфейсе и назначение их будет одинаковым, хотя реализация может отличаться в корне. Именно потому интерфейсы и не имеют реализации методов, что в разных типах реализация может коренным образом отличаться друг от друга, но с точки зрения обрабатывающего кода это будут одни и те же методы. Ну как-то так |
| Автор: fell 30.8.2012, 10:56 |
| extension методы похожи в принципе, в руби однако гибче подход, там можно и статические методы использовать и инстансовые. Однако сдается мне применяют их не часто, чего не скажешь о руби, где это достаточно популярный способ расширить функциональность класса без наследования. |
| Автор: Экскалупатор 30.8.2012, 11:45 |
не соглашусь, применяют достаточно часто. вопрос в необходимости. мне к примеру этот подход не очень нравится, теряется какая то четкость. так что использую только если по другому никак. я может не совсем понял что ты хочешь сделать, но ты же можешь отнаследовать два интерфейса в одном классе, реализовать все методы обоих интерфейсов и дальше наследоваться уже от этого класса. и будет тебе счастье в виде всех имплементированных методов в одном наследнике. но сдается мне этот код начнет плохо пахнуть... |
| Автор: Экскалупатор 31.8.2012, 22:48 | ||
)) ну я не настаиваю на абсолютности своего мнения. мне просто не очень нравится когда в проекте существует +100500 расширений, скажем, для string, и в итоге получается что мы можем вызвать этот метод для любой вообще строки в проекте. это единственное что мне не очень нравится в этом подходе. в остальном я только за. понятно, что все нужно применять с умом, но порой некоторые плюшки в кривых руках, становятся похожи на бензопилу в руках у макаки, и никто не может поручиться, что она решит вытворить в следующий момент |
| Автор: diadiavova 1.9.2012, 01:17 | ||||
Кто мешает актуальные для конкретного круга задач расширения оформить в отдельном пространстве имен и импортировать это пространство именно (и только) там, где этот круг задач решается?
В кривых руках все что угодно может иметь точно такой же эффект. Что до расширений, то при разумном использовании они дают огромные возможности и нет разумных причин, для того, чтобы ими не воспользоваться. |
| Автор: diadiavova 1.9.2012, 10:10 | ||
Перечитал это еще раз. В первый раз не понял о чем речь, думал ты говоришь о реализации нескольких интерфейсов просто. Ну в таком виде это действительно фигня, тем более, что это можно и без интерфейсов реализовать, они тут как бы вообще ни причем. Интерфейсам можно добавить те же расширения и тогда они будут доступны везде, где эти интерфейсы реализованы, но опять-таки это целесообразно делать в тех случаях, когда интерфейс содержит методы достаточно низкого уровня, с которыми работать неудобно, но их вполне достаточно для целей, выполняемых интерфейсом, тогда расширения просто предоставляют более удобные средства для работы с интерфейсом. А так как ты написал, проще создать экземпляр класса и вызывать его методы при необходимости, так что тут не только интерфейсы не нужны, но и наследование не имеет смысла. |
| Автор: fell 1.9.2012, 10:35 |
| В понимании интерфейсов я немного продвинулся после заметки от доктора ) Просто где то слышал фразу, что мол проблему множественного наследования в С# и некоторых других языках решают интерфейсы. По факту это оказалось немного не так. По поводу использовать методы нескольких классов через инстансы, подход очевидный, но почему тогда применяют модули в руби, а не работают с инстансами. Можно даже не через инстансы, а просто объявить класс статическим типа Concole.Write() и пользоваться методами класса без создания экземпляров. |
| Автор: diadiavova 1.9.2012, 10:59 | ||
Видишь ли, у меня такое ощущение, что ты малость недопонимаешь суть наследования. Если рассматривать наследование только как инструмент передачи функциональности наследникам, то интерфейсы тут как бы вообще ни при делах. С другой стороны зачем тогда вообще наследование нужно, если можно прекрасно работать с экземплярами других классов или, как ты говоришь, вообще делать методы статическими и не париться? Ты забываешь, что при том же наследовании существуют еще абстрактные и виртуальные методы, которые позволяют переопределить в наследниках элементы поведения базового класса или (в случае с абстрактными методами) определить его с нуля. Вот с этой задачей интерфейсы прекрасно справляются. То есть интерфейс очень похож на абстрактный класс, с той лишь разницей, что в абстрактном классе могут присутствовать реализованные методы, а в интерфейсе их нет. Фактически интерфейс - это инструмент, с помощью которого разные классы могут между собой взаимодействовать, не накладывая дополнительных ограничений, которые есть, если использовать класс. Простой пример: ты создаешь библиотеку, которой будут пользоваться другие программы. Есть в ней какой-то метод, выполняющий некоторую обработку передаваемого ему объекта. Если ты определишь тип аргумента, указав класс, то ограничишь круг обрабатываемых объектов этим классом и его подклассами. В то же самое время, в этом методе ты можешь вызывать пару-тройку простых методов аргумента и наличия этих методов в аргументе вполне достаточно, чтобы объект можно было обработать. Так вот вопрос в том, какой смысл ограничивать круг возможных аргументов одним классом, когда можно типизировать его интерфейсом, в котором объявлены именно те методы и с той сигнатурой, которые требуются для данного случая? Далее, если кому-то надо будет обработать собственный объект твоим методом, ему достаточно будет реализовать в своем классе этот интерфейс(без ограничений по наследованию) и твой метод спокойно проглотит этот объект. То есть с помощью интерфейса создатель класса показывает другим классам как нужно работать с этим объектом. А что такое модули в руби? В бейсике например, в модуле все члены статические и доступны глобально везде где доступен модуль(то есть ссылаться на модуль не обязательно при вызове метода). А в руби это что-то подобное? |
| Автор: fell 3.9.2012, 10:32 | ||||||
Модуль в руби это mix-in, что то вроде абстрактного класса, только с полной реализацией методов. То есть в классе указываем, какой модуль используем и можем пользоваться методами модуля.
Для большей наглядности.
в C# получается наиболее похожая тема extension методы. Хотя если подключить класс через using, то можно так же пользоваться методами подключенного класса. |
| Автор: diadiavova 3.9.2012, 10:59 |
| fell, в бейсике модуль действует похожим образом, только импортировать ( или как ты говоришь, подключить через юзинг)надо не модуль, а пространство имен, в котором он определен и все члены будут доступны без ссылки на модуль. А ещё там можно импортировать класс и будут доступны все статические члены без ссылки на класс(в модуле все члны статические). Но это всё не рассматривается как подмешивание, скорее напоминает глобальные методы, свойства и пр. Только всё это интерфейсов не заменяет. |