На этом шаге мы рассмотрим особенности выполнения такого замещения.
В производном классе некоторые поля и методы (и другие члены) наследуются из базового класса, а часть полей и методов описывается непосредственно в производном классе. Может статься, что член, описанный в производном классе, имеет такое же название, как и член, наследуемый из базового класса. Такая ситуация называется замещением члена класса. Она вполне законна и может использоваться. Единственное условие состоит в том, что при описании в производном классе поля или метода, название которого совпадает с названием поля или метода, наследуемого из базового класса, необходимо использовать инструкцию new.
Из того, что поле или метод из базового класса замещаются в производном классе, вовсе не следует, что соответствующее поле или метод больше недоступны в производном классе. Замещаемый член класса существует одновременно с тем членом, который описан в производном классе. Просто если мы обращаемся к члену класса по его названию, то по умолчанию обращение выполняется к тому члену, который описан в производном классе. Если нам нужно получить доступ к замещенному члену класса, то перед его названием через точку указывается ключевое слово base.
Пример, в котором используется замещение членов класса, представлен в примере ниже.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace pr144_1 { // Базовый класс: class Base { // Целочисленное поле: public int code; // Метод для отображения значения поля: public void show(){ Console.WriteLine("Класс Base: " + code); } // Конструктор с одним аргументом: public Base(int n){ code = n; } } // Производный класс: class MyClass: Base { // Новое поле замещает одноименное поле, // унаследованное из базового класса: new public int code; // Новый метод замещает одноименный метод, // унаследованный из базового класса: new public void show(){ // Вызов версии метода из базового класса: base.show(); // Обращение к полю производного класса: Console.WriteLine("Класс MyClass: " + code); } // Метод для присваивания значения полю, унаследованному // из базового класса и замещенному в производном // классе: public void set(int n) { // Обращение к полю, унаследованному из базового // класса и замещенному в производном классе: base.code = n; } // Конструктор с двумя аргументами: public MyClass(int m, int n): base(m) { // Присваивание значения полю производного класса: code = n; } } // Класс с главным методом: class Program { // Главный метод: static void Main() { // Создание объекта производного класса: MyClass obj = new MyClass(100, 200); // Отображение значений полей объекта: obj.show(); Console.WriteLine(); // Присваивание значения замещенному полю: obj.set(300); // Присваивание значения замещающему полю: obj.code = 400; // Отображение значений полей объекта: obj.show(); // Задержка: Console.ReadLine(); } } }
Результат выполнения программы такой.
Рис.1. Результат выполнения программы
Базовый класс Base содержит целочисленное поле code, метод show(), отображающий в консоли сообщение с названием класса и значением поля, а также конструктор с одним аргументом, определяющим значение целочисленного поля.
В производном классе MyClass также описывается поле code и метод show(). И поле, и метод описаны с инструкцией new. Если мы в теле класса используем идентификатор code или вызываем метод show(), то имеются в виду именно те члены класса, которые описаны непосредственно в классе MyClass. Чтобы получить доступ к полю, унаследованному из базового класса и замещенному в производном, используем инструкцию base.code. Чтобы вызвать версию метода show() из базового класса, используем инструкцию base.show().
Инструкцию base.show() мы используем в теле метода show(), который описывается в классе MyClass. Это означает, что при вызове метода show() из объекта класса MyClass первой командой в теле метода вызывается версия метода show(), описанная в классе Base. В результате в консольном окне отображается значение поля code, унаследованного из класса Base и замещенного в классе MyClass. Затем командой
Console.WriteLine("Класс MyClass: " + code);
Инструкция base.code использована нами в теле метода set(), предназначенного для присваивания значения полю code, замененному в производном классе.
В главном методе программы командой
MyClass obj = new MyClass(100, 200);
obj.show();
Командой obj.set(300); новое значение присваивается замещенному полю code, а командой
obj.code = 400;
obj.show(); .
На следующем шаге мы рассмотрим переопределение виртуальных методов.