Интерфейс определяет набор методов, которые должны быть реализованы классом, наследующим этот интерфейс. Сам интерфейс не реализует методы.
Интерфейсы объявляются с помощью ключевого слова interface. Вот как выглядит упрощенная форма объявления интерфейса:
Interface имя
{
тип_возврата имя_метода_1 (список_параметров);
тип_возврата имя_метода_2 (список_параметров);
. . . . . . . .
тип_возврата имя_метода_N (список_параметров);
}
Интерфейсы синтаксически подобны абстрактным классам.
Однако в интерфейсе ни один метод не может включать тело, т.е. интерфейс, в принципе, не предусматривает какой бы то ни было реализации.
Он определяет, что должно быть сделано, но не уточняет, как.
Какой-либо интерфейс может унаследовать и реализовать любое количество классов. И каждый по-своему. При этом один класс может реализовать любое число разных интерфейсов.
Для реализации интерфейса класс должен обеспечить тела (реализацию) методов, описанных в интерфейсе. Каждый класс может определить собственную реализацию. Таким образом, два класса могут реализовать один и тот же интерфейс различными способами, но все классы поддерживают одинаковый набор методов.
Поскольку интерфейс для всех объектов одинаков, это позволяет программе, “осведомленной” о наличии интерфейса, использовать объекты любого класса.
Рассмотрим пример интерфейса для класса, который генерирует ряд чисел.
Public interface ISeries
{
int getNext (); // Возвращает следующее число ряда.
void reset (); // Выполняет перезапуск.
void setStart (int x); // Устанавливает начальное значение.
}
Этот интерфейс имеет имя ISeries. Хотя префикс "I" необязателен, многие программисты его используют, чтобы отличать интерфейсы от классов. Интерфейс ISeries объявлен открытым, поэтому он может быть реализован любым классом в любой программе.
Помимо сигнатур методов интерфейсы могут объявлять сигнатуры свойств, индексаторов и событий.
Так как в интерфейсе методы не содержат реализации, то:
• нельзя создать экземпляр интерфейса;
• интерфейсы не могут иметь полей, так как это подразумевает некоторую внутреннюю реализацию;
• они не могут определять конструкторы, деструкторы или операторные методы;
• кроме того, ни один член интерфейса не может быть объявлен статическим;
• все методы в классе-интерфейсе по умолчанию являются открытыми и виртуальными, однако при их реализации писать override не нужно.
Реализация интерфейсов
Формат записи класса, который реализует интерфейс:
class имя_класса : имя_интерфейса
{
// тело класса
}
Если класс реализует интерфейс, он должен это сделать в полном объеме, т.е. реализация интерфейса не может быть выполнена частично.
Классы могут реализовать несколько интерфейсов. В этом случае имена интерфейсов отделяются запятыми.
Класс может наследовать базовый класс и реализовать один или несколько интерфейсов. В этом случае список интерфейсов должен возглавлять имя базового класса.
Рассмотрим пример реализации интерфейса ISeries, объявление которого было приведено выше. Здесь создается класс с именем ByTwos, генерирующий ряд чисел, в котором каждое следующее число больше предыдущего на два.
Class ByTwos : ISeries
{
int start;
int val;
public ByTwos()
{
start = 0;
val = 0;
}
public int getNext()
{
val += 2;
return val;
}
public void reset()
{
val = start;
}
public void setStart(int x)
{
start = x;
val = start;
}
// Здесь могут быть дополнительные члены
}
Рассмотрим пример, демонстрирующий использование интерфейса, реализованного классом ByTwos.
using System;
Class SeriesDemo
{
public static void Main()
{
ByTwos ob = new ByTwos();
if (ob is ISeries)
Console.WriteLine("Объект реализует интерфейс ISeries");
else throw new Exception ("Объект НЕ реализует ISeries");
for (int i = 0; i < 5; i++)
Console.WriteLine("Следующее значение = " + ob.getNext());
Console.WriteLine("\nПереход в исходное состояние.");
ob.reset();
for (int i = 0; i < 5; i++)
Console.WriteLine("Следующее значение = " + ob.getNext());
Console.WriteLine("\nНачинаем с числа 100.");
ob.setStart(100);
for (int i = 0; i < 5; i++)
Console.WriteLine("Следующее значение = " + ob.getNext());
}
}
}
Рассмотрим пример другой реализации интерфейса. Класс Primes генерирует ряд простых чисел. Обратите внимание на то, что его способ реализации интерфейса ISeries в корне отличается от используемого классом ByTwos.
Class Primes : ISeries
{
int start;
int val;
public Primes()
{
start = 2;
val = 2;
}
public int getNext()
{
int i, j;
bool isprime;
val++;
for (i = val; i < 1000000; i++)
{
isprime = true;
for (j = 2; j < (i / j + 1); j++)
{
if ((i % j) == 0)
{
isprime = false;
break;
}
}
if (isprime)
{
val = i;
break;
}
}
return val;
}
public void reset()
{
val = start;
}
public void setStart(int x)
{
start = x;
val = start;
}
}
Дата: 2019-02-02, просмотров: 304.