Зачем мне нужен интерфейс?

Возможный дубликат:
Интерфейсы: Почему я не могу их понять?
Почему я хочу использовать интерфейсы?

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

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

- спасибо заранее.

Примечание. Я задаю этот вопрос в контексте языка .NET(С#)

Edit1: на данный момент всякий раз, когда я пытаюсь узнать интерфейс, мой разум говорит мне → "приятель, вы собираетесь нарисовать кого-то тело в белом листе". Но вам нужен еще один белый лист, чтобы снова нарисовать контур, нарисовать все части тела, заполнить их цветами, чтобы получить реальную картину ". Так почему я трачу первый белый лист, чтобы получить схему.

Ответ 1

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

Поставщики базы данных:

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

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

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

Коллекции:

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

Полиморфизм

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

И, конечно, я должен дать свой любимый полиморфный пример С++, пример животных. Все животные имеют определенные характеристики. Допустим, они могут двигаться, говорить, и все они имеют имя. Поскольку я только что определил, что общего у всех моих животных, и я могу абстрагировать эти качества в интерфейсе 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

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

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

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

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

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

РЕДАКТИРОВАТЬ: Рассмотрим это:

У вас есть приложение, которое должно хранить некоторые данные Say EntityA, но у вас может быть несколько способов хранения данных (например, xml, база данных SQL, ect CSV). Вы можете создать класс для каждого из этих разных методов для хранения EntityA. но когда вы хотите изменить метод, вам нужно явно указать тип, который вы хотите прямо там.

ie

public class DoStuffWithEntityA{
   public void DoStuffAndStoreAsXml(EntityA entity){ /*Logic*/}
   public void DoStuffAndStoreAsCsv(EntityA entity){ /*Logic*/}
   public void DoStuffAndStoreInDatabase(EntityA entity){ /*Logic*/}
}

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

например,

public interface IStoreEntityA{
    void Store(EnitityA entity);
}

то вы можете просто сказать, что хотите что-то, что хранит EntityA в вашем коде

public class DoStuffWithEntityA{
    private IStoreEntityA _entityAStorer;
    public DoStuffWithEntityA(IStoreEntityA howIStoreEntityA){ _entityAStorer = howIStoreEntityA;}
    public void DoStuff(EntityA entity)
    {
        //Do Stuff
        _entityAStorer.Store(entity);
    }
}

Это означает, что ваша логика не тесно связана с тем, как вы храните EntityA