Почему у интерфейса нет реализации? - C #

Я читал некоторые теории кода, связанные с множественным наследованием и интерфейсами. Во всех местах сказано, что interface is a class without implementation.

1) Какая польза от отсутствия реализованных методов / функций в интерфейсе? Это для поддержки нескольких реализаций одного и того же метода в разных классах, наследующих интерфейс?

2) Кажется, что большинство примеров кода демонстрируют void методы интерфейса. Всегда ли функции / методы интерфейса void?


person aspiring    schedule 15.02.2013    source источник
comment
Вам следует попробовать немного поискать, прежде чем размещать вопрос: здесь   -  person bash.d    schedule 15.02.2013
comment
(1) В значительной степени, да. (2) Не обязательно; у вас могут быть непустые методы, свойства, события ...   -  person Rawling    schedule 15.02.2013
comment
Может быть, небольшая предыстория: C # не имеет множественного наследования, как c. В C у вас может быть базовый класс с некоторыми методами, 2 (или более) дочерних класса базового класса, а затем класс внука, который наследуется от обоих дочерних классов. Это широко известно как проблема с алмазами. Должен ли внук вести себя как один из детей и каков из них? java и C # пытаются избежать проблем из этого созвездия, используя абстрактный класс, которым является интерфейс. вы можете реализовать некоторые интерфейсы, но не можете наследовать более чем от одного класса.   -  person Offler    schedule 15.02.2013
comment
@Offler, у меня был отличный разговор здесь, в SO, о MI :) Тем не менее, оцените ваш вклад. Могу я сказать это Class D: A, IB, IC в качестве резюме к последнему разделу вашего комментария? (IB, IC - это два разных интерфейса, поэтому этот класс D наследуется от класса A и двух интерфейсов / абстрактных классов)   -  person aspiring    schedule 15.02.2013
comment
Если вы делаете что-то вроде «class D: A, IB, IC», вы наследуете от класса A. Если A имеет не абстрактные общедоступные методы, вы можете их вызывать. С IB вы только говорите: D содержит реализацию для методов, которые объявлены в IB, но не имеют кода в IB. D реализует код, который необходим для работы в качестве IB. Или, другими словами: вы действительно наследуете A, который объявляет и определяет методы, которые можно использовать; IB только показывает, какая структура нужна, что должно быть что-то с этим именем, если вы реализуете интерфейс в классе.   -  person Offler    schedule 18.02.2013


Ответы (3)


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

Что касается вопроса 2: нет, методы интерфейса могут иметь те же сигнатуры, что и методы класса.

person Dirk Trilsbeek    schedule 15.02.2013
comment
Спасибо. Не могли бы вы привести пример последней причины: Фактическая реализация может быть неизвестна потребителю, поддерживая слабую связь и тестируемость с помощью модульных тестов.? - person aspiring; 15.02.2013
comment
слабая связь в основном используется с контейнерами внедрения зависимостей, такими как Castle Windsor, Unity, NInject или Spring Framework. Чтобы получить общее представление о DI (или инверсии управления как более общем названии шаблона), вам следует изучить несколько руководств, например: joelabrahamsson.com/entry/. Что касается тестируемости: модульные тесты должны тестировать только один модуль, поэтому тестируемый компонент, который полагается на (возможно, много) других компонентов, будет трудно тестировать отдельно. Используя имитирующие фреймворки или заглушки, вы можете упростить модульное тестирование. - person Dirk Trilsbeek; 15.02.2013
comment
Что ж, это выходит за рамки моей шляпы :) Я посмотрел на это руководство с точки зрения interface inheritance не для LinQ. Однако в большинстве статей указано classes implement interfaces вместо classes inherit from interfaces. Подобно тому, что вы упомянули в одном из своих комментариев. Так какая же норма? реализует или наследует? Если да, то почему в этой статье говорится о наследовании? - person aspiring; 15.02.2013
comment
Наследование интерфейса - это концепция, при которой один интерфейс наследует объявления методов от другого интерфейса. Реализация такого интерфейса ничем не отличается от реализации интерфейса, который не наследует объявления каких-либо методов. - person Dirk Trilsbeek; 15.02.2013

1) Какая польза от отсутствия реализованных методов / функций в интерфейсе? Это поддержка нескольких реализаций одного и того же метода в разных классах, наследующих интерфейс?

ДА.

2) Большинство примеров кода, похоже, показывают методы интерфейса void. Всегда ли функции / методы интерфейса недействительны?

Нет, совсем нет. Он может вернуть что угодно.

person Habib    schedule 15.02.2013
comment
Спасибо. Что ж, в первом случае я все еще могу написать родительский класс и унаследовать его один конкретный метод и реализовать его по-разному в нескольких дочерних классах ... Мне удалось это сделать. Так в чем же преимущество помещения этих методов в интерфейс (помимо попытки найти обходной путь множественного наследования)? :) - person aspiring; 15.02.2013
comment
@aspiring, ваш вопрос должен заключаться в следующем: зачем использовать интерфейс? , вы уже упомянули одну из причин в своем комментарии, интерфейс фактически определяет контракт и полезен с полиморфизмом. Вам нужно больше узнать о концепции, это может быть хорошим началом cs.utah.edu/~germain/PPS/Topics/interfaces.html - person Habib; 15.02.2013
comment
Спасибо :) Полезно, вся помощь и статьи. - person aspiring; 15.02.2013

По 1) Да, ваша идея верна. Предположим, у вас есть интерфейс, в котором есть какой-то метод makeSound. Теперь вы можете реализовать этот интерфейс в каком-нибудь Guitar классе и каком-то Drums классе. Вам нужно только знать в своей программе, что у вас есть объект, реализующий makeSound, чтобы вы могли вызвать этот метод. Не нужно знать, каким будет фактический вывод / звук.

Для 2) Нет, интерфейс может содержать методы с любой сигнатурой.

person Dominik Sandjaja    schedule 15.02.2013
comment
То есть вы имеете в виду аналогичный метод Draw() в классе Graphics? Но тогда Guitar должен давать звук гитары, и Drums тоже. Сказать, что когда будет реализован этот метод makeSound, он будет использовать звук реализации дочернего класса? если он был makeShape, он примет форму дочернего класса? - person aspiring; 15.02.2013
comment
Потребуется наиболее подходящая реализация. Если вы override реализация, она будет принята. Поскольку Guitar и Drums не наследуются друг от друга, будет использоваться их соответствующая реализация. - person Dominik Sandjaja; 15.02.2013
comment
@aspiring не воспринимает реализации интерфейса как дочерние классы. Интерфейс представляет собой своего рода обещание того, что объект, реализующий этот интерфейс, будет иметь метод с именем X с подписью Y. В примере DaDaDoms Interface.makeSound на самом деле будет Guitar.makeSound, если ваш объект - гитара. И это было бы Drums.makeSound, если бы объект был типа Drums. - person Dirk Trilsbeek; 15.02.2013