What does it mean to “program to an interface”?
===============================================

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

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

Это просто так, если вы должны были сделать:

Вы можете использовать любой класс, который реализует`IInterface`? Когда вам нужно это сделать? Единственное, о чем я могу думать, это если у вас есть метод, и вы не уверены, какой объект будет передан, за исключением того, что он реализует`IInterface`, Я не могу думать, как часто вам нужно будет это делать.

Кроме того, как вы могли бы написать метод, который принимает объект, который реализует интерфейс? Это возможно?

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

Когда я впервые начал знакомиться с интерфейсами, я тоже был озадачен их актуальностью. Я не понимаю, зачем они тебе нужны. Если мы используем такой язык, как Java или C #, у нас уже есть наследование, и я рассматривал интерфейсы какслабее форма наследования и мысли "зачем беспокоиться?" В некотором смысле я был прав, вы можете рассматривать интерфейсы как своего рода слабую форму наследования, но помимо этого я наконец понял их использование в качестве языковой конструкции, рассматривая их как средство классификации общих черт или поведений, которые были продемонстрированы потенциально много не связанных классов объектов.

Например - скажем, у вас есть игра на SIM-карте и есть следующие классы:

```
class HouseFly inherits Insect {
    void FlyAroundYourHead(){}
    void LandOnThings(){}
}

class Telemarketer inherits Person {
    void CallDuringDinner(){}
    void ContinueTalkingWhenYouSayNo(){}
}

```
Очевидно, что эти два объекта не имеют ничего общего с точки зрения прямого наследования. Но вы могли бы сказать, что они оба раздражают.

Допустим, наша игра должна иметь какую-то случайнуювещь это раздражает игрока, когда они обедают. Это может быть`HouseFly` или`Telemarketer` или и то и другое - но как вы допускаете оба с одной функцией? И как вы просите каждый другой тип объекта «делать их надоедливые вещи» таким же образом?

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

```
interface IPest {
    void BeAnnoying();
}

class HouseFly inherits Insect implements IPest {
    void FlyAroundYourHead(){}
    void LandOnThings(){}

    void BeAnnoying() {
        FlyAroundYourHead();
        LandOnThings();
    }
}

class Telemarketer inherits Person implements IPest {
    void CallDuringDinner(){}
    void ContinueTalkingWhenYouSayNo(){}

    void BeAnnoying() {
        CallDuringDinner();
        ContinueTalkingWhenYouSayNo();
    }
}

```
Теперь у нас есть два класса, каждый из которых может раздражать по-своему. И они не должны происходить из одного и того же базового класса и иметь общие присущие им характеристики - им просто необходимо выполнить договор`IPest` - этот контракт прост. Вы просто должны`BeAnnoying`, В связи с этим мы можем смоделировать следующее:

```
class DiningRoom {

    DiningRoom(Person[] diningPeople, IPest[] pests) { ... }

    void ServeDinner() {
        when diningPeople are eating,

        foreach pest in pests
        pest.BeAnnoying();
    }
}

```
Здесь у нас есть столовая, которая принимает несколько закусочных и количество вредителей - обратите внимание на использование интерфейса. Это означает, что в нашем маленьком мире, член`pests` массив может быть на самом деле`Telemarketer` объект или`HouseFly` объект.

`ServeDinner` Метод вызывается, когда обед подается, и наши люди в столовой должны есть. В нашей маленькой игре именно тогда наши вредители выполняют свою работу - каждый вредитель должен быть раздражен`IPest` интерфейс. Таким образом, мы можем легко иметь как`Telemarketers` а также`HouseFlys` надоедать по-своему - нас волнует только то, что у нас что-то есть`DiningRoom` объект, который является вредным организмом, нам на самом деле все равно, что это такое, и они не могут иметь ничего общего с другими.

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



[Мартин Фаулер: инверсия управляющих контейнеров и шаблон внедрения зависимостей](http://martinfowler.com/articles/injection.html)[Википедия: инверсия контроля](https://en.wikipedia.org/wiki/Inversion_of_Control)В таком случае вы бы не написали так:

Вы бы написали что-то вроде этого:

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

Если мы оставим IoC вне стола, вы можете написать код, который знает, что он может общаться с объектомэто делает что-то конкретное, но не какой тип объекта или как он это делает.

Это пригодится при передаче параметров.

Что касается вашего вопроса в скобках «Кроме того, как вы могли бы написать метод, который принимает объект, который реализует интерфейс? Это возможно?», В C # вы просто использовали бы тип интерфейса для типа параметра, например так:

Это включается прямо в «разговор с объектом, который делает что-то конкретное». Описанный выше метод знает, чего ожидать от объекта, что он реализует все в IInterface, но ему все равно, какой это тип объекта, только то, что он придерживается контракта, то есть интерфейс.

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

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

Позвольте мне привести вам конкретный пример.

У нас есть специальная система перевода для оконных форм. Эта система перебирает элементы управления в форме и переводит текст в каждом. Система знает, как обрабатывать базовые элементы управления, такие как свойство «тип элемента управления, который имеет текст», и аналогичные базовые элементы, но для чего-либо базового она не дотягивает.

Теперь, поскольку элементы управления наследуются от предопределенных классов, которые мы не можем контролировать, мы можем сделать одну из трех вещей:

Создайте поддержку для нашей системы перевода, чтобы точно определить, с каким типом управления она работает, и перевести правильные биты (кошмар обслуживания)Встроить поддержку в базовые классы (невозможно, поскольку все элементы управления наследуются от разных предопределенных классов)Добавить поддержку интерфейсаИтак, мы сделали Nr. 3. Все наши элементы управления реализуют ILocalizable, который представляет собой интерфейс, который дает нам один метод, возможность переводить «себя» в контейнер текста / правил перевода. Таким образом, форме не нужно знать, какой тип элемента управления она нашла, только что она реализует определенный интерфейс и знает, что существует метод, который можно вызвать для локализации элемента управления.



 so I want to give my point of view here, including some extra information what I noticed when using this method.

**Модульное тестирование**

For the last two years, I have written a hobby project and I did not write unit tests for it. After writing about 50K lines I found out it would be really necessary to write unit tests. I did not use interfaces (or very sparingly) ... and when I made my first unit test, I found out it was complicated. Зачем?

Because I had to make a lot of class instances, used for input as class variables and/or parameters. So the tests look more like integration tests (having to make a complete 'framework' of classes since all was tied together).

**Fear of interfaces** So I decided to use interfaces. My fear was that I had to implement all functionality everywhere (in all used classes) multiple times. In some way this is true, however, by using inheritance it can be reduced a lot.

**Combination of interfaces and inheritance** I found out the combination is very good to be used. I give a very simple example.

This way copying code is not necessary, while still having the benefit of using a car as interface (ICar).



`List`, Можно реализовать список с помощью:

внутренний массивСвязанный списокдругая реализацияСоздавая интерфейс, скажем`List`, Вы только код для определения списка или что`List` значит в реальности.

Вы можете использовать любой тип реализации внутренне, скажем,`array` реализация. Но предположим, что вы хотите изменить реализацию по какой-то причине, например, из-за ошибки или производительности. Тогда вам просто нужно изменить декларацию`List<String> ls = new ArrayList<String>()` в`List<String> ls = new LinkedList<String>()`.

В другом месте кода вы не должны будете что-либо менять; Потому что все остальное было построено на определении`List`.



 который я привел студентам, состоит в том, что они должны написать

вместо

Они выглядят точно так же в короткой программе, но если вы продолжите использовать`myList` 100 раз в вашей программе вы можете начать видеть разницу. Первое объявление гарантирует, что вы вызываете только методы`myList` которые определены`List` интерфейс (поэтому нет`ArrayList` конкретные методы). Если вы запрограммировали интерфейс таким образом, позже вы можете решить, что вам действительно нужно

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

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

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

Теперь не имеет значения, какой`List` вы вернетесь, или какой`Map` передается в качестве параметра. Изменения, которые вы делаете внутри`doSomething` Метод не заставит вас изменить код вызова.



You could use any class that implements interface?"  
A: - Yes.

Q: -... "When would you need to do that?"  
A: - Each time you need a class(es) that implements interface(s).

**Замечания:** we couldn't instantiate an interface not implemented by a class - **Правда.**

Зачем?because interface has only methods prototypes, not definitions (just functions names, not their logic)AnIntf anInst = new Aclass();  
// мы могли бы сделать это**только если** Aclass implements AnIntf.  
// anInst will have Aclass reference.

**Замечания:**  
Now we could understand what happend if Bclass and Cclass implements same Dintf.

**What we have:**  
same interface prototypes (functions names in interface), and call different implementations.

Bibliography:  
[Prototypes - wikipedia](https://en.wikipedia.org/wiki/Function_prototype)



**Program to an interface** allows to change implementation of contract defined by interface seamlessly. It allows loose coupling between contract and specific implementations.

`IInterface classRef = new ObjectWhatever()`

You could use any class that implements IInterface? When would you need to do that?

Have a look at this SE question for good example.

[Why should the interface for a Java class be preferred?](https://stackoverflow.com/questions/147468/why-should-the-interface-for-a-java-class-be-prefered/41347099#41347099)

does using an Interface hit performance?

if so how much?

Да. It will have slight performance overhead in sub-seconds. But if your application has requirement to change the implementation of interface dynamically, don't worry about performance impact.

how can you avoid it without having to maintain two bits of code?

Don't try to avoid multiple implementations of interface if your application need them. In absence of tight coupling of interface with one specific implementation, you may have to deploy the patch to change one implementation to other implementation.

One good use case: Implementation of Strategy pattern:

[Пример шаблона стратегии в реальном мире](https://stackoverflow.com/questions/370258/real-world-example-of-the-strategy-pattern/35180265#35180265)



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

Например, я мог бы иметь интерфейс движения. Метод, который заставляет что-то «двигаться», и любой объект (Person, Car, Cat), который реализует интерфейс движения, может быть передан и задан для перемещения. Без метода каждый знает тип класса.



ниям здесь), я настоятельно рекомендую взять копию[Head First Design Patterns](https://oreilly.com/catalog/9780596007126/), Это очень легко прочитать, и он ответит на ваш вопрос напрямую, объяснит, почему это важно, и покажет вам много шаблонов программирования, которые вы можете использовать, чтобы использовать этот принцип (и другие).



CharBuffer, String, StringBuffer, StringBuilder

Эти конкретные классы не имеют общего родительского класса, кроме Object, поэтому ничто не связывает их, кроме того факта, что каждый из них имеет какое-то отношение к массивам символов, представляя их или манипулируя ими. Например, символы String нельзя изменить после создания экземпляра объекта String, тогда как символы StringBuffer или StringBuilder можно редактировать.

Тем не менее, каждый из этих классов способен соответствующим образом реализовать методы интерфейса CharSequence:

В некоторых случаях классы библиотеки классов Java, которые раньше принимали String, были пересмотрены, чтобы теперь принимать интерфейс CharSequence. Поэтому, если у вас есть экземпляр StringBuilder, вместо извлечения объекта String (что означает создание экземпляра нового объекта), вы можете просто передать сам StringBuilder, поскольку он реализует интерфейс CharSequence.

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

BufferedWriter, CharArrayWriter, CharBuffer, FileWriter, FilterWriter, LogStream, OutputStreamWriter, PipedWriter, PrintStream, PrintWriter, StringBuffer, StringBuilder, StringWriter, Writer



 но хочу упомянуть, что строка «Программа для интерфейса, а не для реализации» имела хорошее обсуждение в книге «Шаблоны проектирования GoF (Gang of Four)».

Указано на с. 18:

**Программа для интерфейса, а не реализация**

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

и, кроме того, это началось с:

Есть два преимущества манипулирования объектами исключительно с точки зрения интерфейса, определенного абстрактными классами:

Клиенты остаются в неведении о конкретных типах объектов, которые они используют, пока объекты придерживаются интерфейса, ожидаемого клиентами.Клиенты не знают классов, которые реализуют эти объекты. Клиенты знают только об абстрактных классах, определяющих интерфейс.Другими словами, не пишите свои классы, чтобы`quack()` метод для уток, а затем`bark()` метод для собак, потому что они слишком специфичны для конкретной реализации класса (или подкласса). Вместо этого напишите метод, используя имена, которые являются достаточно общими для использования в базовом классе, например`giveSound()` или же`move()`, так что они могут быть использованы для уток, собак или даже автомобилей, и тогда клиент ваших классов может просто сказать`.giveSound()` а не думать о том, чтобы использовать`quack()` или же`bark()` или даже определить тип, прежде чем выдать правильное сообщение для отправки объекту.



 even when we are not depending on abstractions.

Programming to interfaces **forces us to use a contextually appropriate subset of an object.** That helps because it:

prevents us from doing contextually inappropriate things, andlets us safely change the implementation in the future.For example, consider a `Person` класс, который реализует`Friend` и`Employee` интерфейс.

In the context of the person's birthday, we program to the `Friend` interface, to prevent treating the person like an `Employee`.

In the context of the person's work, we program to the `Employee` interface, to prevent blurring workplace boundaries.

Отлично. We have behaved appropriately in different contexts, and our software is working well.

Far into the future, if our business changes to work with dogs, we can change the software fairly easily. First, we create `Dog` class that implements both `Friend` а также`Employee`, Then, we safely change`new Person()` в`new Dog()`, Even if both functions have thousands of lines of code, that simple edit will work because we know the following are true:

функция`party` uses only the `Friend` подмножество`Person`.функция`workplace` uses only the `Employee` подмножество`Person`.Учебный класс`Dog` implements both the `Friend` а также`Employee` интерфейсы.On the other hand, if either `party` или же`workplace` were to have programmed against `Person`, there would be a risk of both having `Person`-specific code. Changing from `Person` в`Dog` would require us to comb through the code to extirpate any `Person`-specific code that `Dog` does not support.

**The moral**: programming to interfaces helps our code to behave appropriately and to be ready for change. It also prepares our code to depend on abstractions, which brings even more advantages.



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

тогда я мог бы создать GoogleSearchProvider, YahooSearchProvider, LiveSearchProvider и т. д.

затем создайте JpegImageLoader, GifImageLoader, PngImageLoader и т. д.

Большинство надстроек и плагинов работают с интерфейсами.

Другое популярное использование - шаблон Repository. Скажем, я хочу загрузить список почтовых индексов из разных источников

затем я мог бы создать XMLZipCodeRepository, SQLZipCodeRepository, CSVZipCodeRepository и т. д. Для своих веб-приложений я часто создаю XML-репозитории на ранней стадии, чтобы я мог что-то запустить и запустить до того, как база данных Sql будет готова. Когда база данных готова, я пишу SQLRepository, чтобы заменить версию XML. Остальная часть моего кода остается неизменной, так как он работает исключительно на интерфейсах.

Методы могут принимать интерфейсы, такие как:



**Код для интерфейса Не реализация не имеет ничего общего с Java, как и с интерфейсом конструкции.**

Эта концепция была широко известна в книгах «Паттерны / Банды четырех», но, скорее всего, была задолго до этого.Эта концепция, безусловно, существовала задолго до появления Java.

Конструкция Java Interface была создана, чтобы помочь в этой идее (среди прочего), и люди стали слишком сосредоточены на конструкции как на центре смысла, а не на первоначальном намерении. Однако по этой причине у нас есть открытые и закрытые методы и атрибуты в Java, C ++, C # и т. Д.

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

И вы можете программировать для интерфейса, а не для реализации, даже не используя конструкцию интерфейса. Вы можете программировать на интерфейс, а не на реализацию в C ++, которая не имеет конструкции Interface. Вы можете интегрировать две массивные корпоративные системы гораздо надежнее, если они взаимодействуют через открытые интерфейсы (контракты), а не вызывают методы для объектов, внутренних по отношению к системам. Ожидается, что интерфейсы всегда будут реагировать одинаково ожидаемым образом при одинаковых входных параметрах; если реализовано для интерфейса, а не для реализации. Концепция работает во многих местах.

Встряхните мысль о том, что интерфейсы Java имеют какое-либо отношение к концепции «Программа для интерфейса, а не реализация». Они могут помочь применить концепцию, но они**не** концепт.



 абстрактным интерфейсам, как мы видим в Java или .NET. Это даже не концепция ООП.

Что это действительно означает, так это не шутите над внутренностями объекта или структуры данных. Используйте абстрактный программный интерфейс или API для взаимодействия с вашими данными. В Java или C # это означает использование открытых свойств и методов вместо необработанного доступа к полям. Для C это означает использование функций вместо необработанных указателей.

РЕДАКТИРОВАТЬ: И с базами данных это означает использование представлений и хранимых процедур вместо прямого доступа к таблице.



Postman is asked to go home by home and receive the covers contains (letters,documents,cheques,giftcard,application,loveletter) with address written on it to deliver.

Suppose there is no cover and ask post man to go home by home and receive all the things and deliver to other person the postman can get confuse,

so better wrap it with cover(in our story it is interface) then he will do his job fine.

Now postman job is to receive and deliver the covers only..(he dont bothered what is inside in the cover).

Create type of `interface` not actual type, but implement with actual type.

Create to interface means your components get **Fits into the rest of code easily**

I give you example.

you have AirPlane interface as below.

Suppose you have methods in your Controller class of Planes like

а также

implemented in your program. It will not **ПЕРЕРЫВ** your code. I mean, it need not to change as long as it accepts arguments as `AirPlane`.

Because it will accept any Airplane despite of actual type, `flyer`, `highflyr`, `fighter`, так далее.

Also, in a collection:

`List<Airplane> plane;` // Will take all your planes.

The following example will clear your understanding.

You have a fighter plane that implements it, so

The same thing for HighFlyer and other clasess:

Now think your controller classes using `AirPlane` several times,

Suppose your Controller class is ControlPlane like below,

here magic comes as

you may make your new `AirPlane` type instances as many as you want and you are not changing

код`ControlPlane` учебный класс.

you can add instance..

you may remove instances.. of previously created types too.



 что у вас есть продукт под названием «Зебра», который можно расширить с помощью плагинов. Он находит плагины путем поиска DLL в некотором каталоге. Он загружает все эти библиотеки DLL и использует отражение, чтобы найти любые классы, которые реализуют`IZebraPlugin`и затем вызывает методы этого интерфейса для связи с плагинами.

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

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

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



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

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

**РЕДАКТИРОВАТЬ:** Ниже приведена ссылка на статью, где Эрих Гамма обсуждает свою цитату «Программа для интерфейса, а не для реализации».

<http://www.artima.com/lejava/articles/designprinciples.html>



 «Мне нужна эта функциональность, и мне все равно, откуда она».

Рассмотрим (на Java)`List` интерфейс по сравнению с`ArrayList` а также`LinkedList` конкретные классы. Если все, что меня волнует, это то, что у меня есть структура данных, содержащая несколько элементов данных, к которым я должен обращаться через итерацию, я бы выбрал`List` (и это 99% времени). Если я знаю, что мне нужно постоянное время вставки / удаления из любого конца списка, я мог бы выбрать`LinkedList` конкретная реализация (или, более вероятно, использовать[Очередь](https://docs.oracle.com/javase/tutorial/collections/interfaces/queue.html) интерфейс). Если я знаю, что мне нужен произвольный доступ по индексу, я бы выбрал`ArrayList` конкретный класс.



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



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



 вы можете внедрить свои собственные классы (которые отвечают требованиям интерфейса) в класс, который зависит от него



 это способствует слабой связи. Как упомянул @lassevk, Inversion of Control отлично подходит для этого.

**Кроме того, посмотрите в твердых принципах**. [вот видео серия](http://dimecasts.net/Casts/ByTag/SOLID%20Principle)

Он проходит через жестко закодированный (сильно связанный пример), затем просматривает интерфейсы и, наконец, переходит к инструменту IoC / DI (NInject).



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

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

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

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



**Интерфейс** **п.** The set of all signatures defined by an object's operations is called the interface to the object

**Тип** **п.** A particular interface

A simple example of an **интерфейс** as defined above would be all the PDO object methods such as `query()`, `commit()`, `close()` etc., as a whole, not separately. These methods, i.e. its interface define the complete set of messages, requests that can be sent to the object.

A **тип** as defined above is a particular interface. I will use the made-up shape interface to demonstrate: `draw()`, `getArea()`, `getPerimeter()` так далее..

If an object is of the Database type we mean that it accepts messages/requests of the database interface, `query()`, `commit()` etc.. Objects can be of many types. You can have a database object be of the shape type as long as it implements its interface, in which case this would be **sub-typing**.

Many objects can be of many different interfaces/types and implement that interface differently. This allows us to substitute objects, letting us choose which one to use. Also known as polymorphism.

The client will only be aware of the interface and not the implementation.

So in essence programming to an interface would involve making some type of abstract class such as `Shape` with the interface only specified i.e. `draw()`, `getCoordinates()`, `getArea()` etc.. And then have different concrete classes implement those interfaces such as a Circle class, Square class, Triangle class. **Hence program to an interface not an implementation.**



I don't retain `interface`s are the most important thing in a language: it's more commonly used the class inheriting. But anyway they are important!  
For example (this is `Java` code, but it can simply adapted to `C#` or many other languages):



**In simple terms...** If I'm writing a new class Swimmer to add the functionality swim() and need to use an object of class say Dog, and this Dog class implements interface Animal which declares swim()[To better understand...you may draw a diagram as to what I am talking about]. At the top of the hierarchy(Animal) it's very abstract while at the bottom (Dog) it's very concrete. The way I think about "programming to interfaces" is that, as I write Swimmer class, I want to write my code against the interface that's as far up that hierarchy which in this case is Animal object. An interface is free from implementation details and thus makes your code loosely-coupled. The implementation details can be changed with time, however it would not affect the remaining code since all you are interacting is with the interface and not the implementation. You don't care what the implementation is like...all you know is that there will be a class that would implement the interface.



Думайте об интерфейсе как о ваших открытых методах классов.

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

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

Смысл всего этого в том, что вы можете предоставить любой другой алгоритм / класс поиска, если он предоставляет интерфейс, от которого зависит Vector (поиск по пузырькам, последовательный поиск, быстрый поиск).

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

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

Что касается «упущения» в отношении того, как все работает; большой (по крайней мере, в C ++), поскольку именно так работает большая часть стандартной библиотеки TEMPLATE.

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

Это огромная тема и один из основополагающих принципов проектирования шаблонов.



 where you want your implementation class to implement methods written in the contract (interface). Since Java does not provide multiple inheritance, "programming to interface" is a good way to achieve multiple inheritance.

If you have a class A that is already extending some other class B, but you want that class A to also follow certain guidelines or implement a certain contract, then you can do so by the "programming to interface" strategy.



"Program to interface" means don't provide hard code right the way, meaning your code should be extended without breaking the previous functionality..