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

3.7.1Скрытие имени.

Область сущности обычно заключает больше текста программы, чем область объявления сущности. В частности, область сущности может включать объявления, представляющие новые области объявлений, содержащие сущности с одинаковыми именами. Такие объявления приводят к тому, что исходная сущность становится скрытой. И наоборот, сущность считается видимой, если она не скрыта.

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

3.7.1.1Скрытие через вложение.

Скрытие имени через вложение возникает в результате вложения пространств имен или типов в рамках пространств имен, в результате вложения типов в рамках классов или структур и в результате объявлений параметров и локальных переменных.

Пример:

class A { int i = 0;

void F() { int i = 1; }

void G() { i = 1; } }

в рамках метода F переменный экземпляр i скрыт локальной переменной i, но в рамках метода G экземпляр i все еще ссылается на переменный экземпляр.

Когда имя во внутренней области скрывает имя внешней области, скрываются все перегруженные вхождения данного имени. Пример:

class Outer { static void F(int i) {}

static void F(string s) {}

class Inner { void G() { F(1); // Invokes Outer.Inner.F F("Hello"); // Error }

static void F(long l) {} } }

вызов F(1) приводит к вызову F, объявленному в Inner, так как все внешние вхождения F скрыты внутренним объявлением. По той же причине вызов F("Hello") приводит к ошибке времени компилирования.

3.7.1.2Скрытие через наследование

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

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

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

  • Индексатор, представленный в классе или структуре, скрывает все индексаторы базового класса с такой же сигнатурой (попадания и типы параметра).

Правила, управляющие объявлениями операторов (§10.10), делают невозможным для производного класса объявление оператора с сигнатурой, аналогичной сигнатуре оператора базового класса. Поэтому операторы никогда не скрывают друг друга.

В противоположность скрытию имени из внешней области, скрытие доступного имени из унаследованной области приводит к предупреждению. В этом примере:

class Base { public void F() {} }

class Derived: Base { public void F() {} // Warning, hiding an inherited name }

объявление F в Derived приводит к предупреждению. Скрытие наследуемого имени не является ошибкой, поскольку это препятствует отдельному развитию базовых классов. Например, вышеуказанная ситуация могла наступить, так как более поздняя версия Base представила метод F, который не был представлен в более ранней версии класса. Если бы вышеупомянутая ситуация была ошибочной, любое изменение, сделанное для базового класса в библиотеке класса отдельной версии, могло потенциально привести к недопустимости производных классов.

Предупреждение, вызванное скрытием унаследованного имени, можно устранить с помощью модификатора new:

class Base { public void F() {} }

class Derived: Base { new public void F() {} }

Модификатор new указывает, что F в Derived является «новым», и что действительно требуется скрыть унаследованный член.

Объявление нового члена приводит к скрытию унаследованного члена только в рамках области нового члена.

class Base { public static void F() {} }

class Derived: Base { new private static void F() {} // Hides Base.F in Derived only }

class MoreDerived: Derived { static void G() { F(); } // Invokes Base.F }

В вышеуказанном примере объявление F в Derived приводит к скрытию F, унаследованного от Base, но, так как новый F в Derived имеет частный доступ, его область не распространяется на MoreDerived. Поэтому вызов F() в MoreDerived.G действителен, и он приведет к вызову Base.F.

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