C# - Главная Пространство имен
► System ► Microsoft Для учеников (начинающих)
► Видео уроки ► Обучение ► Примеры программ ► Секреты в Си Шарп Для профессионалов
► Обучение ► Примеры программ ► Задачки - для тебя! |
Реализация интерфейсов C#Итак, если интерфейс определен, один или несколько классов могут его реализовать. Чтобы реализовать интерфейс, нужно указать его имя после имени класса подобно тому, как при создании производного указывается базовый класс. Формат записи класса, который реализует интерфейс, таков: class имя_класса : имя_интерфейса { // тело класса } Нетрудно догадаться, что имя реализуемого интерфейса задается с помощью элемента имя_интерфейса. Если класс реализует интерфейс, он должен это сделать в полном объеме, т.е. реализация интерфейса не может быть выполнена частично. Классы могут реализовать несколько интерфейсов. В этом случае имена интерфейсов отделяются запятыми. Класс может наследовать базовый класс и реализовать один или несколько интерфейсов. В этом случае список интерфейсов должно возглавлять имя базового класса. Методы, которые реализуют интерфейс, должны быть объявлены открытыми. Дело в том, что методы внутри интерфейса неявно объявляются открытыми, поэтому их реализации также должны быть открытыми. Кроме того, сигнатура типа в реализации метода должна в точности совпадать с сигнатурой типа, заданной в определении интерфейса. Рассмотрим пример реализации интерфейса ISeries, объявление которого приведено выше. Здесь создается класс с именем ByTwos, генерирующий ряд чисел, в котором каждое следующее число больше предыдущего на два. // Реализация интерфейса ISeries, 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 реализует все три метода, определенные интерфейсом ISeries. Иначе и быть не может, поскольку классу не разрешается создавать частичную реализацию интерфейса. Рассмотрим пример, демонстрирующий использование класса ByTwos, Вот его код: // Демонстрация использования интерфейса, // реализованного классом ByTwos. using System; class SeriesDemo ( public static void MainO { ByTwos ob = new ByTwos(); 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("Следующее значение равно " + Iob.getNext()) ; Console.WriteLine("\n Начинаем с числа 100."); ob.setStart(100); for(int i=0; i < 5; 1++) Console.WriteLine("Следующее значение равно " +' ob.getNext()); } } Чтобы скомпилировать программу SeriesDemo, необходимо включить в процесс компиляции файлы, которые содержат классы ISeries, ByTwos и SeriesDemo. Для создания выполняемой программы компилятор автоматически скомпилирует все три файла. Если эти файлы называются, например, ISeries, cs, ByTwos. cs и SeriesDemo.es, то программа скомпилируется посредством выполнения такой командной строки: >csc SeriesDemo.cs ISeries.cs ByTwos.cs Если вы используете интегрированную среду (IDE) Visual Studio, добавьте все эти три файла в свой С#-проект. Вполне допустимо также поместить их в один файл. В классах, которые реализуют интерфейсы, можно определять дополнительные члены. Например, в представленную ниже версию класса ByTwos добавлен метод getPrevious (), который возвращает предыдущее значение ряда. // Реализация интерфейса ISeries с дополнительно // определяемым методом getPrevious(). class ByTwos : ISeries { int start; int val; int prev; public ByTwos() { start = 0; val = 0; prev = -2; } public int getNext(){ prev = val; val +- 2; return val; } public void reset() { val = start; prev = start - 2; ) public void setStart(int x) { start = x; val - start; Iprev = val - 2; // Метод, не объявленный в интерфейсе ISeries. public int getPrevious<) { return prev; Обратите внимание на то, что добавление метода getPrevious () потребовало внесения изменений в реализацию методов, определенных интерфейсом iSeries. Но поскольку интерфейс для этих методов остается прежним, при изменении не разрушается код, написанный ранее. В этом и заключается одно из достоинств использования интерфейсов. Возможно, вы будете несколько удивлены, узнав, что можно объявить ссылочную переменную интерфейсного типа. Другими словами, можно создать переменную-ссылку на интерфейс. Такая переменная может ссылаться на любой объект, который реализует ее интерфейс. При вызове метода для объекта посредством интерфейсной ссылки будет выполнена та версия указанного метода, которая реализована этим объектом. Этот процесс аналогичен использованию ссылки на базовый класс для доступа к объекту производного класса. Использование интерфейсной ссылки демонстрируется в следующем примере. Здесь используется одна и та же интерфейсная переменная-ссылка, чтобы вызывать методы для объектов как класса ByTwos, так и класса Primes. // Демонстрация использования интерфейсных ссылок. using System; // Определение интерфейса, public interface ISeries { int getNextO; // Возвращает следующее число ряда. void reset О; // Выполняет перезапуск. void setStart(int х); // Устанавливает начальное // значение. } // Используем интерфейс ISeries для генерирования // последовательности четных чисел, class ByTwos : ISeries { int start; int val; public ByTwosО { start = 0; val = 0; } public int getWext{) { val +=2; return val; } public void reset{) { val = start; } public void setStart(int x) { start = x; val = start; } } // Используем интерфейс ISeries для построения // ряда простых чисел, 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); { 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; ) } class SeriesDemo2 { public static void Main() { ByTwos twoOb - new ByTwos(); Primes primeOb = new Primes(); ISeries ob; for(int i=0; i < 5; i++) { ob = twoOb; Console.WriteLine( "Следующее четное число равно ob.getNext()) ; ob = primeOb; Console.WriteLine( "Следующее простое число равно ob.getNext()); Вот результаты выполнения этой программы: (Следующее четное число равно 2 Следующее простое число равно 3 Следующее четное число равно А Следующее простое число равно 5 Следующее четное число равно 6 Следующее простое число равно 7 Следующее четное число равно 8 Следующее простое число равно 11 Следующее четное число равно 10 Следующее простое число равно 13 В методе Main() объявляется переменная ob как ссылка на интерфейс iSeries. Это означает, что ее можно использовать для хранения ссылок на любой объект, который реализует интерфейс ISeries. В данном случае она служит для ссылки на объекты twoOb и primeOb, которые являются экземплярами классов ByTwos и Primes, соответственно, причем оба класса реализуют один и тот же интерфейс, ISeries. Важно понимать, что интерфейсная ссылочная переменная "осведомлена" только о методах, объявленных "под сенью" ключевого слова interface. Следовательно, интерфейсную ссылочную переменную нельзя использовать для доступа к другим переменным или методам, которые может определить объект, реализующий этот интерфейс.
Просмотров: 5828 |