- •Вопрос 1. Общее понятие ооп
- •Вопрос 2. Классы, объекты, абстрагирование
- •Вопрос 3. Полиморфизм, инкапсуляция, наследование
- •Вопрос4. История развития и базовый синтаксис с#
- •Вопрос 5. Основные черты языка с#
- •Перечисления
- •Вопрос 6. Система типов с#
- •Вопрос 7. Литералы, переменные, константы, перечисления Литералы. Представление значений
- •Переменные элементарных типов. Объявление и инициализация
- •Константы
- •Вопрос 8. Операции и выражения
- •Приоритет операций
- •Вопрос 9. Приведение типов
- •Вопрос 10 Контроль за перевыполнением
- •Вопрос 11 Процедурные и функциональные методы в с#
- •Вопрос 11 Создание и уничтожение объектов
- •Модификатор static и объект this Кроме выше рассмотренных модификаторов доступа (public,protected…) в языке c# существует еще ряд модификаторов. Один из них – модификатор static.
- •Уничтожение объектов в управляемой памяти. Деструктор
- •Вопрос 13 Параметризованные классы и индексаторы
- •Параметризованные классы – классы, позволяющие определить тип своих аргументов при непосредственном создании объектов.
- •Вопрос 14 управляющие операторы
- •Вопрос 15 массивы
- •Вопрос 16 перегрузка операций
- •Вопрос 17 Наследование. Конструкторы базового и производного классов
- •Вопрос 18 Переопределение членов базового класса:new модификатор
- •Вопрос 19 Прекращение наследования: sealed-спецификатор
- •Вопрос 20 Абстрактные функции и абстрактные классы
- •Вопрос 21 Операции is и as
- •Вопрос 22 Ввод и вывод данных с#
- •Потоки: байтовые, символьные, двоичные
- •Консольный ввод/вывод. Функции – члены класса Console
- •Консольный вывод. Форматирование
- •Нестандартное (custom) форматирование значений
- •Консольный ввод. Преобразование значений
Вопрос 18 Переопределение членов базового класса:new модификатор
Воп При объявлении членов производного класса в C# разрешено использовать те же самые имена, которые применялись при объявлении членов базового класса. Это касается как методов, так и данных — членов объявляемых классов.
В этом случае соответствующие члены базового класса считаются переопределенными.
Следующий простой фрагмент кода содержит объявления базового и производного классов. Особое внимание в этом примере следует уделить ключевому слову new в объявлении одноименных членов в производном классе. В данном контексте слово new выступает в качестве модификатора, который используется для явного обозначения переопределяемых членов базового класса:
Листинг 7.2.
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;
}
}
}
При переопределении наследуемого члена его объявление в классе-наследнике должно предваряться модификатором new. Если этот модификатор в объявлении производного класса опустить – ничего страшного не произойдет. Транслятор всего лишь выдаст предупреждение об ожидаемом спецификаторе new в точке объявления переопределяемого члена класса.
Дело в том, что переопределенные члены базового класса при "взгляде" на производный класс "извне" не видны. В производном классе они замещаются переопределенными членами, и непосредственный доступ к этим членам возможен только из функций — членов базового и производного классов. При этом для обращения к переопределенному члену из метода производного класса используется ключевое слово base.
По мнению создателей языка C#, тот факт, что ранее (до момента его переопределения) видимый член (базового) класса стал недоступен и невидим извне (в результате его переопределения в производном классе), требует явного дополнительного подтверждения со стороны программиста.
Объявление класса может содержать вложенное (или внедренное) объявление класса. C# допускает и такие объявления:
class X
{
public class XX
{
}
}
Одновременное включение явного объявления класса или структуры с одним и тем же именем в базовый и производный классы также требует явной спецификации с помощью модификатора new:
class X
{
public class XX
{
}
}
class Y:X
{
new public class XX
{
}
}
Модификатор new используется при переопределении общедоступных объявлений и защищенных объявлений в производном классе для явного указания факта переопределения. Этот модификатор используется при объявлении класса-наследника в том случае, если надо скрыть факт наследования объявляемого члена класса.
public class MyBaseC
{
public int x;
public void Invoke()
{
:::::
}
}
Объявление члена класса Invoke в наследуемом классе скрывает метод Invoke в базовом классе:
public class MyDerivedC : MyBaseC
{
new public void Invoke()
{
:::::
}
}
А вот данное-член x не было скрыто в производном классе соответствующим членом, следовательно, остается доступным в производном классе.
Сокрытие имени члена базового класса в производном классе возможно в одной из следующих форм:
константа, поле, свойство или внедренный в класс тип или структура скрывают ВСЕ одноименные члены базового класса;
внедренный в класс или структуру метод скрывает в базовом классе свойства, поля, типы, обозначенные тем же самым идентификатором, а также одноименные методы с той же самой сигнатурой;
объявляемые в производном классе индексаторы скрывают одноименные индексаторы в базовом классе с аналогичной сигнатурой.
Одновременное использование в производном классе члена базового класса и его переопределенного потомка является ошибкой.
В этом примере и базовый BC-, и производный DC-классы используют одно и то же имя для обозначения объявляемого в обоих классах члена типа int. New-модификатор подчеркивает факт недоступности члена x базового класса в производном классе. Однако из производного класса все-таки можно обратиться к переопределенному полю базового класса с использованием полного квалифицированного имени:
using System;
public class BC
{
public static int x = 55;
public static int y = 22;
}
public class DC : BC
{
new public static int x = 100; // Переопределили член базового класса
public static void Main()
{
// Доступ к переопределенному члену x:
Console.WriteLine(x);
// Доступ к члену базового класса x:
Console.WriteLine(BC.x);
// Доступ к члену y:
Console.WriteLine(y);
}
}
В производном классе DC переопределяется вложенный класс C.
В рамках производного класса легко можно создать объект — представитель вложенного переопределенного класса C. Для создания аналогичного объекта — представителя базового класса необходимо использовать полное квалифицированное имя:
using System;
public class BC
{
public class C
{
public int x = 200;
public int y;
}
}
public class DC:BC
{
new public class C // Вложенный класс базового класса скрывается
{
public int x = 100;
public int y;
public int z;
}
public static void Main()
{
// Из производного класса виден переопределенный вложенный класс:
C s1 = new C();
// Полное имя используется для доступа к классу, вложенному в базовый:
BC.C s2 = new BC.C();
Console.WriteLine(s1.x);
Console.WriteLine(s2.x);
}
}
