- •1.2 Понятия приложения, проекта, решения
- •1.3 Среда разработки Visual Studio .Net
- •1.4 Создание первого проекта
- •1. 5 Компиляция и выполнение программы в среде clr
- •2.1 Основы технологии ооп
- •2.2 Состав языка
- •2.3 Типы данных
- •2.4 Переменные и константы
- •2.5 Организация ввода-вывода данных. Форматирование
- •3.1 Некоторые операции с#
- •Отрицание:
- •Условная операция.
- •3.2 Выражения и преобразование типов
- •3.3 Перечень операций
- •3.4 Математические функции языка с#
- •4.1 Операторы следования
- •4.2 Операторы ветвления
- •4.3 Операторы цикла
- •4.4 Операторы безусловного перехода
- •5.1 Методы: основные понятия
- •5.2 Перегрузка методов
- •6.1 Прямая рекурсия
- •6.2 Косвенная рекурсия
- •7.1 Оператор try
- •7.2 Операторы checked и unchecked
- •7.3 Генерация собственных исключений
- •7.4 Приемы использования обработчиков исключений
- •8.1 Одномерные массивы
- •8.2 Массив как параметр
- •8.3 Массив как объект
- •8.4 Многомерные массивы
- •8.5 Ступенчатые массивы
- •8.6 Оператор foreach и его использование при работе с массивами
- •Примеры
- •9.1 Символы char
- •9.2 Неизменяемые строки string
- •9.3 Изменяемые строки
- •Вариант 1
- •Вариант 2
- •Редактирование текста;
- •10.1 Метасимволы в регулярных выражениях
- •10.2 Поиск в тексте по шаблону
- •10.3 Редактирование текста
- •11.1 Байтовый поток
- •11.2 Символьный поток
- •11.3 Двоичные потоки
- •11.4 Перенаправление стандартных потоков
- •Практикум
- •12.1.Работа с файловой системой: классы Directory и Filе и классы DirectoryInfo и FileInfo
- •12.2 Класс FileSystemInfo
- •12.3 Класс DirectoryInfo
- •12.4 Класс Directory
- •2. Реализуем метод, позволяющий получить по имени узла полное имя соответствующей папки
- •12.2 Работа с файлами
- •12.5 Класс File
- •13.1. Классы: основные понятия, данные, методы, конструкторы, свойства
- •13.2 Данные: поля и константы
- •13.3 Методы
- •Конструкторы экземпляра
- •13.4 Конструкторы класса
- •13.5 Свойства
- •13.6 Один класс - один файл
- •13.7. Классы: деструкторы, индексаторы Деструкторы
- •Индексаторы
- •13.8 Операции класса
- •14.1 Иерархия и наследование
- •Использование защищенного доступа
- •14.2 Наследование конструкторов
- •Позволяет вызвать конструктор базового класса:
- •Позволяет получить доступ к члену базового класса, который скрыт "за" членом производного класса.
- •14.3 Многоуровневая иерархия
- •14.4 Переменные базового класса и производного класса
- •14.5 Виртуальные методы
- •14.6 Абстрактные методы и классы
- •14.7 Запрет наследования
- •Самостоятельная работа
- •15.1. Пользовательские и стандартные интерфейсы
- •15.2 Стандартные интерфейсы .Net
- •15.3 Структуры
- •Задание
- •16.1. Классификация коллекций.
- •16.2 Коллекции общего назначения
- •16.3 Класс Stack
- •16.4 Класс Queue
- •16.5 Класс ArrayList
- •16.6 Класс Hashtable
- •17.1 Струткура простейшего windows-приложения
- •17.2 Элементы управления на форме
- •17.3 Обработка событий
- •17.4 Работа с элементами управления
- •17.5 Кнопки
- •17.6 Работа с элементами управления в режиме работы приложения
- •17.7 Работа со списками: ListBox, ComboBox, NumericUpDown.
- •17.8 Работа с переключателями: RadioButton, CheckBox
- •18.1 Рисование в форме
- •18.2 Работа с изображениями
14.4 Переменные базового класса и производного класса
С# является языком со строгой типизацией, в нем требуется строгое соблюдение совместимости типов с учетом стандартных преобразований типов. Из чего следует, что переменная одного типа обычно не может ссылаться на объект другого ссылочного типа. За одним небольшим исключением - ссылочная переменная базового класса может ссылаться на объект любого производного класса. Продемонстрируем это на примере:
class DemoPoint
{
public int x;
public int y;
public void Show()
{
Console.WriteLine("точка на плоскости: ({0}, {1})",x, y);
}
public DemoPoint (int x, int y)
{
this.x=x; this.y=y;
}
}
class DemoShape : DemoPoint
{
public int z;
new public void Show()
{
Console.WriteLine("точка в пространстве: ({0}, {1}, {2})", x, y, z);
}
public DemoShape(int x, int y, int z):base(x, y)
{
this.z=z;
}
}
class Program
{
static void Main()
{
DemoPoint point1 = new DemoPoint(0,1);
Console.WriteLine("({0}, {1})",point1.x,point1.y);
DemoShape pointShape = new DemoShape(2,3,4);
Console.WriteLine("({0}, {1}, {2})",pointShape.x, pointShape.y, pointShape.z);
DemoPoint point2=pointShape; //допустимая операция
//ошибка - не соответствие типов указателей
//pointShape=point1;
Console.WriteLine("({0}, {1})", point2.x, point2.y);
//ошибка, т.к. в классе DemoPoint нет поля z
//Console.WriteLine("({0}, {1}, {2})", point2.x, point2.y, point2.z);
}
}
Ошибка возникнет и при попытке через объект point2 обратиться к методу Show. Например, point2.Show(). В этом случае компилятор не сможет определить, какой метод Show вызвать - для базового или для производного класса. Для решения данной проблемы можно воспользоваться таким понятием как полиморфизм, который основывается на механизме виртуальных методов.
14.5 Виртуальные методы
Виртуальный метод - это метод, который объявлен в базовом классе с использованием ключевого слова virtual, и затем переопределен в производном классе с помощью ключевого слова override. При этом если реализована многоуровневая иерархия классов, то каждый производный класс может иметь свою собственную версию виртуального метода. Этот факт особенно полезен в случае, когда доступ к объекту производного класса осуществляется через ссылочную переменную базового класса. В этой ситуации С# сам выбирает какую версию виртуального метода нужно вызвать. Этот выбор производится по типу объекта, на которую ссылается данная ссылка. Например:
class DemoPoint //базовый класс
{
protected int x;
protected int y;
public virtual void Show() //виртуальный метод
{
Console.WriteLine("точка на плоскости: ({0}, {1})",x, y);
}
public DemoPoint (int x, int y)
{
this.x=x; this.y=y;
}
}
class DemoShape : DemoPoint //производный класс
{
protected int z;
public override void Show() //перегрузка виртуального метода
{
Console.WriteLine("точка в пространстве: ({0}, {1}, {2})", x, y, z);
}
public DemoShape(int x, int y, int z):base(x, y) //конструктор производного класса
{
this.z=z;
}
}
class DemoLine : DemoPoint //производный класс
{
protected int x2;
protected int y2;
public override void Show() //перегрузка виртуального метода
{
Console.WriteLine("отрезок на плоскости: ({0}, {1})-({2},{3})",x,y, x2, y2);
}
public DemoLine(int x1, int y1, int x2, int y2):base(x1, y1)
{
this.x2 = x2; this.y2 = y2;
}
}
class Program
{
static void Main()
{
DemoPoint point1 = new DemoPoint(0,1);
point1.Show();
DemoShape pointShape = new DemoShape(2,3,4);
pointShape.Show();
DemoLine line = new DemoLine(0,0, 10, 10);
line.Show();
Console.WriteLine();
//использование ссылки базового класса на объекты производных классов
DemoPoint point2=pointShape;
point2.Show();
point2=line;
point2.Show();
}
}
Таким образом, благодаря полиморфизму через ссылочную переменную возможно обращаться к объектам разного типа, а также с помощью одного и того же имени выполнять различные действия.