Поиск по сайту:

Что делает интерфейс в объектно-ориентированном программировании?


Одним из ключевых компонентов объектно-ориентированных языков, таких как Java и C#, является возможность писать классы с использованием интерфейсов, которые стандартизируют определения методов и обеспечивают расширенный полиморфизм. Мы обсудим, что они из себя представляют и как их использовать.

Формализованный полиморфизм

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

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

  1. public interface IEnumerable
  2. {
  3.     IEnumerator GetEnumerator();
  4. }

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

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

Например, циклы foreach на самом деле просто используют .GetEnumerator(), поэтому они будут поддерживать любой тип коллекции, который реализует IEnumerable, например Списки, словари и хэш-наборы.

  1. void Main()
  2. {
  3.     foreach(var item in  IEnumerable) 
  4.     {
  5.        // do something
  6.     }
  7. }

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

Интерфейсы также можно использовать вместо параметров типа. Например, у вас может быть собственная коллекция CustomList < T> . Это работает для любого типа, но если вы хотите вызвать определенный метод для каждого элемента, вы не сможете, так как компилятор не знает, поддерживает ли используемый тип этот метод. Единственными вариантами, которые вы получите, будут методы для базовых объектов.

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

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

Использование интерфейсов

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

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

Visual Studio довольно необычна, и если вы нажмете «показать потенциальные исправления», вы получите возможность для VS автоматически добавить шаблон интерфейса в ваш класс. Вам, очевидно, потребуется заменить NotImplementedExceptions.

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

Написание собственных интерфейсов

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

Вы можете использовать {get; набор; } для неявного указания свойств, что также работает при их реализации в реальном классе:

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




Все права защищены. © Linux-Console.net • 2019-2024