2008-10-27 3 views
59

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

+2

Люди, он не просил определения. – 2008-10-27 15:04:47

+2

Я долго боролся со всем интерфейсом и наследованием. В чем разница между наследованием абстрактного класса и реализацией интерфейса, например? Ни один учитель не дошел до меня до тех пор, пока я не прочитал «Первая глава - образцы дизайна». Это легкий и не такой дорогой. – 2008-10-27 15:16:44

+3

Технически интерфейс представляет собой класс с абстрактными методами. Таким образом, Java на самом деле имеет множественное наследование (разрешено только для интерфейсов). Причина этого в том, что проблема с множественным наследованием в основном связана с переменными экземпляра. (и частично реализации метода) – Hugo 2008-10-27 15:51:25

ответ

1

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

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

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

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

3

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

Классическим примером может быть метод IVehicle, который имеет метод Move(). У вас могут быть классы Car, Bike и Tank, которые реализуют IVehicle. Они могут все Move(), и вы могли бы написать код, который не заботился о том, с каким транспортным средством он имел дело, просто для Move().

void MoveAVehicle(IVehicle vehicle) 
{ 
    vehicle.Move(); 
} 
+0

Это действительно работает даже без интерфейсов. (Duck typing.) Интерфейсы просто позволяют вам рассказать компилятору о своих намерениях. – Hugo 2008-10-27 15:52:58

+2

На самом деле, транспортное средство не обязательно должно быть интерфейсом, это может быть базовый класс. Интерфейсы более подходят для служб или аналогичных, где вы просто заботитесь о контракте, а не о наследовании, поэтому я считаю, что полиморфизм на самом деле не важен для интерфейсов. – Hugo 2008-10-27 15:55:00

+0

Да, ты прав. Но обычно есть интерфейс, который определяет методы суперкласса. И в определенном смысле интерфейс является суперклассом, без реализации. – 2008-10-27 17:35:46

51

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

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

Тогда любой случайный человек может прийти, создать класс, который реализует этот интерфейс, создать экземпляр объекта этого класса и передать его в мой код библиотеки и ожидать его работы. Примечание. Конечно, можно строго реализовать интерфейс, игнорируя намерение интерфейса, поэтому просто реализовать интерфейс не гарантирует, что все будет работать. Глупо всегда находит путь! :-)

Еще один конкретный пример: две команды, работающие с различными компонентами, которые должны сотрудничать. Если две команды сядут на 1-й день и договорились о наборе интерфейсов, тогда они могут пойти своими разными путями и реализовать свои компоненты вокруг этих интерфейсов. Команда A может создавать тестовые жгуты, которые имитируют компонент из команды B для тестирования, и наоборот. Параллельное развитие и меньшее количество ошибок.

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

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

0

Как вы отметили, интерфейсы хороши, когда вы хотите заставить кого-то сделать его в определенном формате.

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

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

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

0

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

0

Во-первых, они дают вам дополнительный слой абстракции . Вы можете сказать: «Для этой функции этот параметр должен быть объектом, который имеет эти методы с этими параметрами». И вы, вероятно, хотите также установить значение этих методов, в некотором смысле абстрагированных условиях, но позволяя вам рассуждать о коде. В утка-типа языков вы получаете это бесплатно. Нет необходимости в явных синтаксических «интерфейсах». Тем не менее, вы, вероятно, все еще создаете набор концептуальных интерфейсов , что-то вроде контрактов (например, в Design by Contract).

Кроме того, интерфейсы иногда используются для менее «чистых» целей. В Java они могут использоваться для эмуляции множественного наследования. В C++ вы можете использовать их для сокращения времени компиляции.

В общем, они уменьшают сцепление в коде. Это хорошая вещь.

Ваш код может быть проще протестировать таким образом.

8

Интерфейсы определяют контракты, и это ключевое слово.

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

Итак, давайте посмотрим пример. Предположим, у вас есть метод, который предоставляет функции для сортировки списка. Первое. Что такое список? Вам действительно все равно, какие элементы он выполняет, чтобы отсортировать список? Ваш ответ не должен быть ... В .NET (например) у вас есть интерфейс IList, который определяет операции, которые список ДОЛЖЕН поддерживать, поэтому вам не нужны фактические данные под поверхностью.

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

interface IComparable 
{ 
    // Return -1 if this is less than CompareWith 
    // Return 0 if object are equal 
    // Return 1 if CompareWith is less than this 
    int Compare(object CompareWith); 
} 

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

IComparable comp1 = list.GetItem(i) as IComparable; 

if (comp1.Compare(list.GetItem(i+1)) < 0) 
    swapItem(list,i, i+1) 

PS: Я знаю примеры, немного наивные, но они являются примерами ...

2

Интерфейсы являются одной из форм полиморфизма. Пример:

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

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

Сценарии файлов C в основном представляют собой интерфейс «что-то, что я могу читать и/или писать байты из и/или в», и почти каждый типизированный язык имеет такие интерфейсы, скрывающиеся в его стандартных библиотеках: потоки или что-то еще. Нетипированные языки обычно имеют неформальные типы (возможно, называемые контрактами), которые представляют потоки. Поэтому на практике вам почти никогда не приходится самостоятельно изобретать этот конкретный интерфейс: вы используете то, что дает вам язык.

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

7

Один типичный пример - архитектура плагина. Разработчик A пишет основное приложение и хочет убедиться, что все плагины, написанные разработчиками B, C и D, соответствуют тому, что их приложение ожидает от них.

0

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

Затем вы можете указать интерфейс ICollection с методами add(), remove() и contains().

Код, который не должен знать, какая коллекция (List, Array, Hash-table, Red-black tree и т. Д.) Может принимать объекты, которые реализовали интерфейс и работать с ними, не зная их фактического типа.

0

В .Net я создаю базовые классы и наследую их, когда классы каким-то образом связаны. Например, базовый класс Person может быть унаследован Employee и Customer. У человека могут быть общие свойства, такие как адресные поля, имя, телефон и т. Д. Сотрудник может иметь свой собственный отдел. У клиента есть другие эксклюзивные свойства.

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

4

Педали на автомобиле реализуют интерфейс. Я из США, где мы едем по правой стороне дороги. Наши рулевые колеса находятся на левой стороне автомобиля. Педали для механической коробки передач слева направо - это сцепление -> тормоз -> ускоритель. Когда я отправился в Ирландию, вождение было отменено. Рулевое колесо автомобилей находится справа, и они едут по левой стороне дороги ... но педали, а педали ... они реализовали один и тот же интерфейс ... все три педали были в одном порядке ... поэтому, даже если класс был другим, и сеть, в которой работает этот класс, была другой, я все еще был доволен интерфейсом педали. Моему мозгу удалось назвать мои мышцы на этом автомобиле, как и на любой другой машине.

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

0

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

Интерфейсы могут иметь различные цели:

  • Обеспечить различные реализации одной и той же цели. Типичный пример - это список, который может иметь различные варианты исполнения для различных вариантов использования производительности (LinkedList, ArrayList и т. Д.).
  • Разрешить изменение критериев. Например, функция сортировки может принимать сопоставимый интерфейс , чтобы предоставил любой тип критериев сортировки, , основанный на том же алгоритме.
  • Скрыть детали реализации. Это также облегчает пользователю чтение , так как в теле интерфейса есть только методы, поля и комментарии, не длинный фрагментов кода для пропуска.

Вот полный текст статьи: http://weblogs.manas.com.ar/ary/2007/11/

1

Представьте себе следующий базовый интерфейс, который определяет основной механизм CRUD:

interface Storable { 
    function create($data); 
    function read($id); 
    function update($data, $id); 
    function delete($id); 
} 

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

Таким образом, вы теперь могли иметь что-то вроде следующего:

class Logger { 
    Storable storage; 

    function Logger(Storable storage) { 
     this.storage = storage; 
    } 

    function writeLogEntry() { 
     this.storage.create("I am a log entry"); 
    } 
} 

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

Следующий вопрос, возникающий из этого, заключается в том, что если базы данных и файлы CSV и т. Д. Могут хранить данные, не должны ли они наследоваться от общего объекта Storable и, таким образом, устраняются необходимость в интерфейсах? Ответ на этот вопрос не является ... не каждое подключение к базе данных может реализовывать операции CRUD, и то же самое относится к каждому файловому считывателю.

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

0

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

Например:

public interface IExample 
{ 
    void Foo(); 
} 

public class Example : IExample 
{ 
    // explicit implementation syntax 
    void IExample.Foo() { ... } 
} 

/* Usage */ 
Example e = new Example(); 

e.Foo(); // error, Foo does not exist 

((IExample)e).Foo(); // success 
0

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

Заканчивать Head First Design Patterns

0

Лучший код Java я когда-либо видел определены почти все ссылки на объекты как экземпляры интерфейсов вместо экземпляров классов , Это сильный признак качественного кода, разработанного для гибкости и изменения.

5

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

Пример 1: Есть много различных поставщиков баз данных, MySQL, MSSQL, Oracle и т.д. Однако все объекты базы данных могут сделать то же самое, так что вы найдете множество интерфейсов для объектов базы данных. Если объект реализует IDBConnection, он предоставляет методы Open() и Close(). Поэтому, если я хочу, чтобы моя программа была агностикой базы данных, я программирую интерфейс, а не конкретным провайдерам.

IDbConnection connection = GetDatabaseConnectionFromConfig() 
connection.Open() 
// do stuff 
connection.Close() 

См путем программирования к интерфейсу (IDbConnection) теперь я могу выгрузить любой поставщик данных в моей конфигурации, но мой код остается точно такой же. Эта гибкость может быть чрезвычайно полезна и удобна в обслуживании. Недостатком этого является то, что я могу выполнять только «общие» операции с базой данных и не могу полностью использовать силу, которую предлагает каждый конкретный провайдер, так как со всем в программировании у вас есть компромисс, и вы должны определить, какой сценарий вам больше всего пригодится.

Пример 2: Если вы заметили, что почти все коллекции реализуют этот интерфейс, называемый IEnumerable. IEnumerable возвращает IEnumerator, который имеет MoveNext(), Current и Reset(). Это позволяет C# легко перемещаться по вашей коллекции. Причина, по которой он может это сделать, заключается в том, что он предоставляет интерфейс IEnumerable, который ЗНАЕТ, что объект предоставляет методы, необходимые для его прохождения. Это делает две вещи. 1) петли foreach теперь будут знать, как перечислить коллекцию, и 2) теперь вы можете применить мощные выражения LINQ к своей коллекции. Опять же, почему интерфейсы настолько полезны здесь, потому что все коллекции имеют что-то в COMMON, их можно перемещать.Каждая коллекция может перемещаться по-другому (связанный список против массива), но красота интерфейсов заключается в том, что реализация скрыта и не имеет отношения к потребителю интерфейса. MoveNext() дает вам следующий элемент в коллекции, это не имеет значения, КАК он это делает. Довольно приятно, да?

Пример 3: Когда вы разрабатываете свои собственные интерфейсы, вам просто нужно задать себе один вопрос. Что общего у этих вещей? Когда вы найдете все, что разделяет объекты, вы абстрагируете эти свойства/методы в интерфейсе, чтобы каждый объект мог наследовать его. Затем вы можете запрограммировать несколько объектов с использованием одного интерфейса.

И, конечно, я должен привести свой любимый полиморфный пример C++, пример животных. Все животные имеют определенные характеристики. Допустим, они могут двигаться, говорить, и все они имеют имя. Поскольку я только что определил, что общего у всех моих животных, и я могу абстрагировать эти качества в интерфейсе IAnimal. Затем я создаю объект Bear, объект Owl и объект Snake, реализующий этот интерфейс. Причина, по которой вы можете хранить разные объекты вместе, реализующие один и тот же интерфейс, состоит в том, что интерфейсы представляют собой повторную передачу IS-A. Медведь IS-A животное, сова IS-A животное, поэтому он делает, так как я могу собрать их всех как Животных.

var animals = new IAnimal[] = {new Bear(), new Owl(), new Snake()} // here I can collect different objects in a single collection because they inherit from the same interface 

foreach (IAnimal animal in animals) 
{ 
    Console.WriteLine(animal.Name) 
    animal.Speak() // a bear growls, a owl hoots, and a snake hisses 
    animal.Move() // bear runs, owl flys, snake slithers 
} 

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

Итак, самое главное с интерфейсами - это то, что объединяет объекты, чтобы вы могли программировать против РАЗНЫХ объектов по ИСПОЛЬЗУЕМОЙ дороге. Экономит время, создает более гибкие приложения, скрывает сложность/реализацию, моделирует объекты/ситуации в реальном мире, среди многих других преимуществ.

Надеюсь, это поможет.

2
When you need different classes to share same methods you use Interfaces.