Российский Государственный Технологический Университет им. К.Э. Циолковского
Опубликован: 02.03.2007 | Доступ: свободный | Студентов: 5678 / 802 | Оценка: 3.96 / 3.45 | Длительность: 27:04:00
ISBN: 978-5-9556-0086-4
Лекция 7:

Наследование и полиморфизм

< Лекция 6 || Лекция 7: 123456 || Лекция 8 >

Переопределение членов базового класса

При объявлении членов производного класса в C# разрешено использовать те же самые имена, которые применялись при объявлении членов базового класса. Это касается как методов, так и данных — членов объявляемых классов.

В этом случае соответствующие члены базового класса считаются переопределенными.

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

using System;
namespace Inheritance_2
{
class X
 {
public X(){}	
public X(int key){}

public int q0;
public int q;
public void fun0()
 {
Console.WriteLine("class X, function fun0()");
q = 125;
 } 	 

public void fun1()
 {
Console.WriteLine("class X, function fun1()");
 } 	 
 }

class Y:X
{
public Y(int key){}
public Y():base(125){} 	 
new public int q; // Если опустить модификатор new – 
new public void fun1() // появится предупреждение об ожидаемом new...
 {
base.fun1(); // Обращение к переопределенным членам базового класса.
base.q = 125;
Console.WriteLine("class Y, function fun1()");
 }	 
static void Main(string[] args)
 {
Y y0 = new Y();
Y y1 = new Y(125);
// А извне переопределенные члены базового класса не видны. 
y0.fun1();
y0.q = 100;
y0.fun0();
y0.q0 = 125;
 }
}
}
Листинг 7.2.

При переопределении наследуемого члена его объявление в классе-наследнике должно предваряться модификатором new. Если этот модификатор в объявлении производного класса опустить – ничего страшного не произойдет. Транслятор всего лишь выдаст предупреждение об ожидаемом спецификаторе new в точке объявления переопределяемого члена класса.

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

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

Объявление класса может содержать вложенное (или внедренное) объявление класса. C# допускает и такие объявления:

class X
{
public class XX
 {
 }
}

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

class X
 {
public class XX
 {
 }
}

class Y:X
{
new public class XX 
 {	 
 }
}

Модификатор new используется при переопределении общедоступных объявлений и защищенных объявлений в производном классе для явного указания факта переопределения.

Наследование и new-модификатор

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

public class MyBaseC 
{
public int x;
public void Invoke()
{
:::::
}
}

Объявление члена класса Invoke в наследуемом классе скрывает метод Invoke в базовом классе:

public class MyDerivedC : MyBaseC
{
new public void Invoke()
{
:::::
}
}

А вот данное-член x не было скрыто в производном классе соответствующим членом, следовательно, остается доступным в производном классе.

Сокрытие имени члена базового класса в производном классе возможно в одной из следующих форм:

  • константа, поле, свойство или внедренный в класс тип или структура скрывают ВСЕ одноименные члены базового класса;
  • внедренный в класс или структуру метод скрывает в базовом классе свойства, поля, типы, обозначенные тем же самым идентификатором, а также одноименные методы с той же самой сигнатурой;
  • объявляемые в производном классе индексаторы скрывают одноименные индексаторы в базовом классе с аналогичной сигнатурой.

Одновременное использование в производном классе члена базового класса и его переопределенного потомка является ошибкой.

< Лекция 6 || Лекция 7: 123456 || Лекция 8 >
kewezok kewezok
kewezok kewezok
Елена Шляхт
Елена Шляхт
Объясните плиз в чем отличие а++ от ++а
Почему результат разный?
int a=0, b=0;
Console.WriteLine(a++); //0
Console.WriteLine(++b); //1
a++;
++b;
Console.WriteLine(a); //2
Console.WriteLine(b); //2