Почему я хочу использовать интерфейсы?

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

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

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

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

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

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

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

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

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

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

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

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

 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: Я знаю, что примеры немного наивны, но это примеры ...

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

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

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

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

Пример 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 } 

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

Таким образом, самое главное с интерфейсами – это то, что объединяет объекты, так что вы можете программировать против РАЗЛИЧНЫХ объектов одним и тем же способом. Экономит время, создает более гибкие приложения, скрывает сложность / реализацию, моделирует объекты / ситуации в реальном мире, среди многих других преимуществ.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Например:

 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 

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

Ознакомьтесь с шаблонами Head First Design

Есть еще несколько ответов на аналогичный вопрос: Интерфейс vs Base Class

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

  • интерфейс как параметр метода в Java
  • Зачем использовать интерфейсы, множественное наследование и интерфейсы, преимущества интерфейсов?
  • Java8: почему запрещается определять метод по умолчанию для метода из java.lang.Object
  • Должны ли быть объявлены методы в интерфейсе Java с модификатором открытого доступа или без него?
  • Список трансляции в список
  • Объяснение интерфейсов для учащихся
  • Оператор «instanceof» ведет себя по-разному для интерфейсов и classов
  • Есть ли шаблон для инициализации объектов, созданных с помощью контейнера DI
  • Почему нет статических методов в интерфейсах, но статические поля и внутренние classы в порядке?
  • Java - объявление из типа интерфейса вместо classа
  • Как вы объявляете интерфейс на C ++?
  • Interesting Posts

    Android-эмулятор – проблема с созданием учетных записей пользователей

    Как я могу размножать и делить, используя только смещение и добавление битов?

    Как удаленно выйти из Google Chrome?

    Ожидания восстановления файлов NTFS

    Keras binary_crossentropy vs categorical_crossentropy performance?

    Каков наилучший способ проверить подключение к Интернету с помощью .NET?

    Скопируйте список файлов, содержащихся в txt-файле, в другую папку

    Excel VBA – Range.Copy транспонированная паста

    Рассчитать количество будних дней между двумя датами в Java

    Удалить текст с кнопки «Назад», удерживая значок

    Поймать исключение, вызванное асинхронным методом

    Как выровнять несколько графиков ggplot2 и добавить тени поверх них

    Время ожидания истекло. Период ожидания истекает до завершения операции или сервер не отвечает. Заявление было прекращено

    Как узнать, поддерживает ли SSD-накопитель TRIM?

    Ошибка Xcode 5 CertUIFramework.axbundle

    Давайте будем гением компьютера.