2010-02-15 5 views
2

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

я есть следующий интерфейс

interface Imammals 
      { 
      walk(); 
      eat(); 
      run(); 
      } 

и у меня есть два класса человека и Cat, который реализует этот интерфейс.

В любом случае, функциональность методов будет отличаться в обоих классах.

Для Eg: прогулки(), функциональность отличается, как кошка использует четыре ноги и человек использует две ноги

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

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

Но здесь интерфейсы помогают нам просто консолидировать декларации методов или есть что-то еще внутри?

EDIT: walking(), running(), running() изменен для ходьбы(), eat(), run() и млекопитающих, был изменен на Imammals.

ответ

3

В вашем сценарии будет выполняться либо наследование типа, либо реализация интерфейса, но абстракция на основе интерфейса позволяет использовать типы вне вашей существующей модели типа для обеспечения функциональности.Это может быть макет объекта, или это может быть какой-то супер-убийственный робот, который может ходить и есть, но на самом деле это не млекопитающее (поэтому наличие inherit из класса Mammal может быть запутанным или просто невозможным).

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

0

Конечно, walking(), eating() будет иметь различную реализацию у разных животных. Но все они walk, run и т. Д. Это все интерфейс говорит.

1

Одним из больших преимуществ интерфейсов является то, что даже в таких языках, как Java и C#, где множественное наследование недопустимо, класс может принимать более одного интерфейса. Что-то может быть как Closable, например, так и List, но не может наследовать от обоих (гипотетических) абстрактных базовых классов AbstractClosable и AbstractList.

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

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

1

Причина, по которой вы хотите, чтобы интерфейс был способен относиться ко всем одинаковым при их командовании.

Тот, кто называет хот() (что довольно странное имя, вероятно, должно быть walk()) просто заинтересовано в том, чтобы сообщить своему животному сделать именно это. Фактическая реализация будет отличаться, но это не то, о чем заботится вызывающий.

+0

Спасибо за указание Конвенции об именах :) –

+0

(для тех, кто видит это и задается вопросом, Шри Кумар отредактировал сообщение соответственно) – Fredrik

0

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

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

2

С помощью интерфейса вы можете иметь следующее:

public void walkMyAnimal(Animal animal) { 
     animal.walk(); 
    } 

без необходимости знать, какое животное именно передается.

+0

Это возможно для DOG и CAT, но как насчет HUMAN и CAT? Не могли бы вы объяснить больше? –

+0

@Sri Kumar, что непонятно? Вы не думаете, что человеку может быть предложено ходить? –

+0

Упс! я прошу прощения. Я думал о части выполнения walk(). –

1

Ну, иногда вы хотите что-то сделать, чтобы «что-нибудь способное бегать», не зная во время разработки, говоришь ли вы о человеке или кошке или что-то еще. Например, представьте себе функцию mammal raceWinner(mammal m1, mammal m2){...} , чтобы вычислить, какое млекопитающее могло бы выиграть в гонке. Чтобы определить, кто победит, возможно, функции необходимо вызвать m1.running() и m2.running(). Конечно, млекопитающие, с которыми мы проходим, действительно будут кошками или людьми или что-то еще, и этот класс поставляет фактическую реализацию running(). Но все raceWinner должно знать, что у них есть метод running() с ожидаемой подписью.

Если определена только running() на cat и human, мы не могли бы назвать m1.running() (поскольку компилятор не гарантирует, что m1 имеет метод running(), так как он знает, что это m1 орудия mammal). Поэтому вместо этого мы должны были бы реализовать raceWinner(human m1, cat m2), а также для двух людей, двух кошек или любой другой пары млекопитающих, которые мы имели в виду, что привело к гораздо большей работе с нашей стороны.

0

Назначение интерфейсов - рассказать вам что a класс делает, а не как оно делает.

Это особенно важно для принятия действий, которые работают по-другому: каждый принтер, который мы подключаем к ПК, работает по-разному, так что каждый сканер, так же как и каждый внешний накопитель. Если всем программам необходимо заботиться о том, как каждый из них работал, вам нужно будет перекомпилировать, скажем, Microsoft Office, для каждой модели принтера, которая выходит.

0

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

Это не всегда возможно, но это решает многие проблемы.

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

2

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

Также вы можете использовать композицию вместо конкретной реализации, если некоторые из ваших объектов имеют общее поведение.

Прочтите немного о шаблоне стратегии Я думаю, что это поможет.

0

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

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

, например, вы могли бы:

class Cat : IMammal, IFourLeggedAnimal 
{ 
} 

class Human: IMammal, ITwoLeggedAnimal 
{ 
} 

Теперь вы можете обращаться с ними обоими, как млекопитающим, с «прогулки()» метод, или вы можете рассматривать их как четыре или два четвероногих животных (не обязательно млекопитающих).

0

Что действительно полезно с интерфейсом, например, млекопитающее - это то, что вы можете обрабатывать массив объектов (людей и кошек) как один и тот же тип, когда вы хотите, чтобы они ходили, ели или бегали.

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

foreach(mammals m in MamalsArrayList){ 
{ 
    m.walking(); 
} 

примечание: я предлагаю вам следовать именования и назвать свои интерфейсы с «Я» перед ними, так что ваш пример должен быть назван IMammals.

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

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

Конечно, у них есть другие виды использования (которые упомянуты в других ответах), я просто сосредоточился на вашем примере.

1

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

-1

Здесь есть две проблемы, которые часто путают. Наследуемое поведение позволяет отвечать на разные «команды» таким же образом, например Man.walk() === Woman.walk(). Полиморфное поведение позволяет одной и той же «команде» реагировать по-разному, например. Animal.move() для одного объекта может отличаться для Animal.move() для другого, птица будет выбирать, чтобы летать, пока слизь будет скользить.

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

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

В вашем конкретном примере Млекопитающее, вероятно, плохое имя интерфейса, потому что оно на самом деле не говорит мне, что он делает, и у него есть потенциал для раздувания тысяч методов. Лучше разделить интерфейсы на очень конкретные случаи. Если вы моделировали животных, у вас может быть интерфейс Moveable с одним методом, move(), на которое каждое животное может отвечать, ходя, бегая, летая или выполняя сканирование по мере необходимости.

Смежные вопросы