Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Yazyk_C_i_osnovy_platformy_NET.docx
Скачиваний:
16
Добавлен:
11.05.2015
Размер:
198.13 Кб
Скачать

17. Интерфейсы

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

Для объявления интерфейса используется ключевое слово interface. Интерфейс содержит только заголовки методов, свойств и событий. Для свойства указываются только ключевые словаgetи (или)set. При объявлении элементов интерфейса не могут использоваться следующие модификаторы:abstract,public,protected,internal,private,virtual,override,static. Считается, что все элементы интерфейса имеютpublic-уровень доступа:

public interface IFlyable

{

voidFly();// метод

doubleSpeed {get;set; }// свойство

}

Чтобы указать, что тип реализует некий интерфейс, используется синтаксис имя-типа : имя-интерфейсапри записи заголовка типа. Если класс является производным от некоторого базового класса, то имя базового класса указывается перед именем реализуемого интерфейса.

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

public class Falcon : IFlyable

{

// неявная реализация интерфейса IFlyable

publicvoidFly() {Console.WriteLine("Falcon flies"); }

publicdoubleSpeed {get;set; }

}

publicclassEagle:IFlyable

{

// обычный метод

publicvoidPrintType() {Console.WriteLine("Eagle"); }

// явная реализация интерфейса IFlyable

voidIFlyable.Fly() {Console.WriteLine("Eagle flies"); }

doubleIFlyable.Speed {get;set; }

}

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

Eagle eagle = new Eagle(); // обычное создание объекта

eagle.PrintType(); // у объекта доступен только этот метод

IFlyable x = eagle; // переменная интерфейса

x.Fly(); // получили доступ к элементам интерфейса

x.Speed = 60;

Все неявно реализуемые элементы интерфейса по умолчанию помечаются в классе как sealed. А значит, наследование классов не ведёт к прямому наследованию реализаций:

publicinterfaceISimple

{

voidM();

}

publicclassBase:ISimple

{

publicvoidM() {Console.Write("Base.M()"); }

}

publicclassDescendant:Base

{

publicvoidM() {Console.Write("Descendant.M()"); }

}

Basex =newBase();

Descendanty =newDescendant();

ISimplexi = x, yi = y;

x.M(); // печатает "Base.M()"

y.M(); // печатает "Descendant.M()"

xi.M(); // печатает "Base.M()"

yi.M(); // печатает "Base.M()"

Чтобы осуществить наследование реализаций, требуется при неявной реализации использовать модификаторы virtualиoverride(при явной реализации использование этих модификаторов невозможно):

publicclassBase:ISimple

{

publicvirtualvoidM() {Console.Write("Base.M()"); }

}

publicclassDescendant:Base

{

publicoverridevoidM() {Console.Write("Descendant.M()"); }

}

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