Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
13
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

13.3Полные имена членов интерфейса

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

interface IControl { void Paint(); }

interface ITextBox: IControl { void SetText(string text); }

полным именем члена Paint является имя IControl.Paint, а полным именем члена SetText — имя ITextBox.SetText.

В приведенном выше примере нельзя указать член Paint как ITextBox.Paint.

Если интерфейс является частью пространства имен, полное имя члена интерфейса включает имя этого пространства имен. Пример:

namespace System { public interface ICloneable { object Clone(); } }

Здесь полным именем метода Clone является имя System.ICloneable.Clone.

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

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

interface ICloneable { object Clone(); }

interface IComparable { int CompareTo(object other); }

class ListEntry: ICloneable, IComparable { public object Clone() {...}

public int CompareTo(object other) {...} }

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

interface IControl { void Paint(); }

interface ITextBox: IControl { void SetText(string text); }

class TextBox: ITextBox { public void Paint() {...}

public void SetText(string text) {...} }

Здесь класс TextBox реализует как класс IControl, так и класс ITextBox.

Если класс C непосредственно реализует интерфейс, все классы, производные от C, также неявно реализуют интерфейс. Базовые интерфейсы, указанные в объявлении класса, могут относиться к интерфейсам сформированного типа (§4.4). Базовый интерфейс не может быть параметром типа сам по себе, хотя он может включать параметры типа, находящиеся в соответствующей области. В следующем коде демонстрируется реализация и расширение сформированных типов классом:

class C<U,V> {}

interface I1<V> {}

class D: C<string,int>, I1<string> {}

class E<T>: C<int,T>, I1<T> {}

Базовые интерфейсы объявления универсального класса должны удовлетворять правилу уникальности, которое изложено в §13.4.2.

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

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

interface IList<T> { T[] GetElements(); }

interface IDictionary<K,V> { V this[K key];

void Add(K key, V value); }

class List<T>: IList<T>, IDictionary<int,T> { T[] IList<T>.GetElements() {...}

T IDictionary<int,T>.this[int index] {...}

void IDictionary<int,T>.Add(int index, T value) {...} }

В этом примере строки IDictionary<int,T>.this и IDictionary<int,T>.Add являются явными реализациями членов интерфейса.

В некоторых случаях имя члена интерфейса может быть неподходящим для реализующего класса. В этом случае член интерфейса может быть реализован с использованием явной реализации члена интерфейса. Например, в классе, который реализует абстракцию файла, скорее всего будет реализована функция-член Close, в результате выполнения этой функции высвобождается файловый ресурс и реализуется метод Dispose интерфейса IDisposable с использованием явной реализации члена интерфейса:

interface IDisposable { void Dispose(); }

class MyFile: IDisposable { void IDisposable.Dispose() { Close(); }

public void Close() { // Do what's necessary to close the file System.GC.SuppressFinalize(this); } }

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

Включение в явную реализацию члена интерфейса модификаторов доступа, а также модификаторов abstract, virtual, override или static, приведет к ошибке при компилировании.

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

Явные реализации члена интерфейса служат двум основным целям:

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

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

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

class Shape: ICloneable { object ICloneable.Clone() {...}

int IComparable.CompareTo(object other) {...} // invalid }

объявление метода IComparable.CompareTo приведет к возникновению ошибки при компилировании, поскольку интерфейс IComparable не включен в список базовых классов класса Shape и не является базовым интерфейсом для интерфейса ICloneable. Аналогичным образом в объявлениях

class Shape: ICloneable { object ICloneable.Clone() {...} }

class Ellipse: Shape { object ICloneable.Clone() {...} // invalid }

объявление метода ICloneable.Clone в классе Ellipse приведет к ошибке при компилировании, поскольку интерфейс ICloneable не указан явно в списке базовых классов класса Ellipse.

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

interface IControl { void Paint(); }

interface ITextBox: IControl { void SetText(string text); }

class TextBox: ITextBox { void IControl.Paint() {...}

void ITextBox.SetText(string text) {...} }

явная реализация члена интерфейса Paint должна быть записана в форме IControl.Paint.

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