Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лр-2(Классы).docx
Скачиваний:
3
Добавлен:
16.08.2019
Размер:
142.88 Кб
Скачать

Реализация интерфейсов

Интерфейсы определяются подобно классам с использованием примерно такого кода:

interface ImyInterface

{

// Члены интерфейса.

}

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

При определении членов интерфейсов не разрешается использовать модификаторы доступа (ни public, ни private, ни protected, ни internai); все члены интерфейсов неявно являются общедоступными.

Члены интерфейсов не могут содержать тело кода.

В интерфейсах не могут определяться члены типа полей.

Члены интерфейсов не могут определяться с использованием таких ключевых слов, как static, virtual, abstract или sealed.

В члены интерфейсов запрещено добавлять определения типов.

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

interface IMyBaseInterfасе

{

void DoSomething();

}

interface IMyDerivedInterfасе : IMyBaseInterfасе

{

new void DoSomething ( );

}

Делается это тем же самым образом, как и сокрытие унаследованных членов класса.

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

interface IMylnterfасе

{

int Mylnt

{

get;

set;

}

}

Здесь y int-свойства MyInt имеется оба блока — и get, и set. В случае свойства с более ограниченным доступом какой-то из них может быть опущен.

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

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

Реализация интерфейсов в классах

В классе, который реализует интерфейс, должны обязательно содержаться реализации для всех членов этого интерфейсов, которые, в свою очередь, должны обязательно соответствовать указанным сигнатурам (а также указанным блокам get и set) и являться общедоступными (public):

public interface IMylnterfасе

{

void DoSomething();

void DoSomethingElse();

}

public class MyClass : IMylnterface

{

public void DoSomething()

{

}

public void DoSomethingElse ( )

{

}

}

Члены интерфейсов допускается реализовать с использованием ключевого слова virtual или abstract, но не ключевого слова static или constant.

public class MyBaseClass

{

public void DoSomething ( )

{

}

}

public class MyDerivedClass : MyBaseClass, IMylnterface

{

public void DoSomethingElse ( )

{

}

}

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

Например:

public interface IMylnterface

{

void DoSomething ();

void DoSomethingElse ();

}

public class MyBaseClass : IMylnterface

{

public virtual void DoSomething ( )

{

}

public virtual void DoSomethingElse ( )

{

}

}

public class MyDerivedClass : MyBaseClass

{

public override void DoSomething ( )

{

}

}

Очевидно, что реализации в базовых классах лучше определять как виртуальные, чтобы в производных классах их можно было заменять, а не скрывать. Если бы пришлось скрывать член базового класса с использованием ключевого слова new, а не переопределять его, как было показано здесь, тогда метод IMyInterfасе. DoSomething всегда бы ссылался на ту версию, которая содержится в базовом классе, даже если бы доступ к производному классу осуществлялся через интерфейс.

Явная реализация членов интерфейса

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

Например, если бы класс MyClass реализовал метод DoSomething интерфейса IMyInterface неявно, как это и было в предыдущем примере, тогда следующий код был бы допустимым:

MyClass myObj = new MyClass ();

myObj.DoSomething();

Такой код тоже был бы допустимым:

MyClass myObj = new MyClass ();

IMylnterface mylnt = myObj;

mylnt.DoSomething( ) ;

Если же MyDerivedClass реализовал бы DoSomething явно, тогда использовать бы можно было только второй прием. Необходимый для этого код выглядит следующим образом:

public class MyClass : IMylnterface

{

void IMylnterface.DoSomething ( )

{

}

public void DoSomethingElse ( )

{

}

}

Здесь метод DoSomething реализуется явно, а метод DoSomethingElse неявно. Получать доступ непосредственно через экземпляр объекта myClass можно только к последнему.

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

public interface IMylnterface

{

int MylntProperty

{

get;

}

}

public class MyBaseClass : IMylnterface

{

protected int mylnt;

public int MylntProperty

{

Get

{

return mylnt;

}

protected set

{

mylnt = value;

}

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]