- •Глава 1. Структура программы на языке с# 6
- •Глава 1. Структура программы на языке с#
- •Задание 1. Вывод строки на экран с использованием esp-последовательности
- •Глава 2. Переменные. Основные типы данных
- •Int.MinValue
- •Задание 2. Описание переменных и преобразование типов
- •Глава 3. Ввод – вывод значений переменных
- •Задание 3. Форматирование вывода
- •Глава 4. Обработка исключительных ситуаций
- •Задание 4. Обработка стандартных исключений
- •Задание 5. Генерация исключений
- •Глава 5. Массивы в c#
- •Initially,
- •Integer array: 1 2 3 4 5
- •Integer array: 1 2 3 4 5
- •Integerarray: 1 2 3 29 30
- •Задание 6. Одномерные массивы
- •Задание 7. Многомерные массивы и массивы массивов
- •Глава 6. Символы и строки
- •If (char.IsLetter(a)) Console.WriteLine("Буква");
- •Задание 8. Работа со строками
- •Глава 7. Описание классов
- •Int m, n;// числитель и знаменатель
- •Пример решения задачи
- •Intyear_tr;
- •If (Enum.IsDefined(typeof(gender_type),value))
- •Int year_tr;
- •If (Enum.IsDefined(typeof(gender_type),value))
- •Задание 9. Описание классов
- •Глава 8. Наследование
- •Задание 10. Наследование
- •Глава 9. Итерфейсы
- •Interface iOutput
- •Void outputName();
- •Interface iOutput
- •Void outputName();
- •If ( a is iOutput )
- •Interface iComparable
- •Int CompareTo( object obj )
- •Задание 11. Стандартные интерфейсы.
- •Глава 10. Файлы
- •Задание 12. Работа с файлами
- •Список использованных источников
Глава 8. Наследование
Наследование – это возможность создания иерархии классов, в которой потомки (производные классы, наследники) получают элементов своих предков (родителей, базовых классов), могут их изменять и добавлять новые.
Класс в C# может иметь произвольное количество потомков и только одного предка. При описании класса имя его предка записывается в заголовке класса после двоеточия. Если имя предка не указано, предком считается базовый класс всей иерархии System.Object:
[ атрибуты ] [ спецификаторы ] class имя_класса [ : предки ]
тело класса
Обратите внимание, что слово "предки" присутствует в описании класса во множественном числе, хотя класс может иметь только одного предка. Причина в том, что класс наряду с единственным предком может наследовать от интерфейсов — специального вида классов, не имеющих реализации, которые будут рассмотрены в следующих лекциях.
Например, создадим производный класс CStudentMasterот базового классаCStudent, предназначенный для храненияданных о студенте магиструры.
class CStudentMaster: CStudent
{
string research;
public CStudentMaster()
{
research = "Unknown";
}
public CStudentMaster(string name, string speciality, gender_type gender, int year_tr, string research):base(name, speciality, gender, year_tr)
{
Year=year_tr;
this.research=research;
}
public string Research
{
get { return research; }
set
{
if (research == "Unknown")
{
if (value == "") name = "Unknown";
else research = value;
}
}
}
new public int Year
{
get { return year_tr; }
set
{ // способ установки свойства
if (value >= 1 && value <= 2)
{
year_tr = value;
}
else throw new Exception("При изменении курса студента указано недопустимое значение. Значение должно быть интевале [1,2]");
}
}
new public void input()
{
base.input();
Year = year_tr;
Console.WriteLine("Введите тему НИР студента");
Research = Console.ReadLine();
}
new public void output()
{
base.output();
Console.WriteLine("research ={0,10}", research);
}
}
Рассмотрим поля и методы производного класса.
Все поля и методы базового класса, кроме конструкторов, наследуются.
Если поля или методы класса – предка имеют тип private, то класс-потомок не имеет к ним прямого доступа и для работы с ними в необходимо использовать открытые методы базового класса.
Если функциям производного класса требуется работать с полями базового, то в базовом классе такие поля можно описать как protected. Поэтому если проектируется иерархия классов, то это более предпочтительный вариант. Таким образом, целесообразно изменить видимость полей в классеCStudentcprivateна protected.
В производном классе могут быть собственные поля и методы.
Если новые поля и методы имеют уникальные имена, то они описываются как обычные поля и методы класса.
В производном классе можно описать поле с таким же именем, что и в базовом классе, возможно, изменив тип этого поля и его модификаторы. В этом случае поле базового класса будет скрыто (не удалено!). Скрытое родительское поле остается доступно в классе-наследнике через обращение base.имя_поля.
В классе CStudentMasterдобавлено одно полеresearchи одно свойство Research.
В производном классе можно добавить метод с таким же именем, что и в базовом классе. При этом возможны три варианта.
Переопределяемый метод отличается списком параметров. Вызов нужного метода определяется обычными правилами перегрузки методов.
Переопределение метода с модификаторами virtual, abstract или override. Это наиболее интересная ситуация, и она будет подробно рассмотрена далее. При переопределении сохраняется заголовок и модификаторы доступа наследуемого метода.
Скрытие метода, т.е. его переопределение с таким же заголовком с модификатором new. Здесь ситуация такая же, как и со скрытием полей. При вызове метода по его имени предпочтение будет отдаваться методу потомка. Это не означает, что метод родителя становится недоступным. В переопределенном методе производного класса вызвать метод базового класса можно обратившись к нему с помощью ключевого слова base, например base.output();В классе CStudentMaster переопределены скрытием методы input(), output(), свойство Year;
Таким образом, переопределение методов реализует принцип полиморфизма.
Полиморфизм - это возможность использовать в различных классах иерархии одно имя для обозначения различных, но сходных по смыслу действий. Чаще всего понятие полиморфизма связывают с механизмом виртуальных методов.
Правила наследования конструкторов класса
Конструкторы класса не наследуются. Следовательно, производный класс должен иметь собственные конструкторы.
Если в производном классе программистом не определен ни один конструктор, то компилятором автоматически создастся конструктор по умолчанию, который вызовет конструктор по умолчанию базового класса и инициализирует все собственные поля значениями по умолчанию.
Если в конструкторе производного класса явный вызов конструктора базового класса отсутствует, то автоматически вызывается конструктор по умолчанию базового класса
В случае необходимости явного вызова конструктора базового класса из конструктора производного класса конструктор производного класса определяют следующим образом имя_производного_класса (список формальных параметров): base(список фактических параметров) {тело}
В случае иерархии классов, конструкторы базовых классов вызываются, начиная с самого верхнего уровня.
Для проверки работы класса можно использовать следующий код.
Console.WriteLine("Для демонстрации методов класса создайте студента магистратуры");
CStudentMaster s = new CStudentMaster();
Console.WriteLine("\nСоздан студент:");
s.output();
Console.WriteLine("\nИзмените данные о студенте:");
s.input();
Console.WriteLine("\nДанные о студенте изменены:");
s.output();
CStudentMaster s1 = new CStudentMaster("Петрова", "Информатика", gender_type.female, 1, "Automata");
Console.WriteLine("\nСоздан новый студент:");
s1.output();