- •Об’єктно-орієнтоване програмування
- •Содержание
- •Тема 1. Понития ооа, ооПр и ооп Лекция 1. Объектная модель и принципы ее организации
- •1. Понития ооа, ооПр и ооп и их отличия от подходов структурного проектирования
- •2. Основные понятия ооп
- •Тема 2. Основы программирования на языке с# .Net Лекция 2. Введение в программирование на с# .Net
- •1. Роль платформы .Net
- •2. Первая программа на c# и основные приемы работы в системе ms Visual Studio
- •3. Структура программы
- •4. Собственные пространства имен
- •Лекция 3. Система типов данных языка с#
- •1. Система типов данных языка с#
- •2. Преобразование типов
- •Лекция 4. Выражения и операторы языка с#
- •1. Выражения
- •2. Операторы
- •2.1. Операторы ввода и вывода
- •2.2. Операторы ветвления
- •2.3. Операторы цикла
- •2.3. Оператор безусловного перехода
- •Лекция 5. Массивы
- •1. Основные понятия
- •2. Одномерные массивы
- •3. Многомерные массивы
- •4. Класс Array
- •5. Класс Random
- •Лекция 6. Структуры и перечисления
- •1. Структуры
- •3. Перечисления
- •Лекция 7. Символы и строки
- •1. Символы char
- •2. Неизменяемые строки string
- •3. Изменяемые строки
- •Лекция 8. Файловая система
- •1. Основные сведения
- •2. Работа с каталогами
- •2.1. Абстрактный класс FileSystemInfo
- •2.2. Класс DirectoryInfo
- •2.3. Класс Directory
- •3. Работа с файлами
- •3.1. Класс Filelnfo
- •3.2. Класс File
- •Тема 3. Принципы парадигмы объектно-ориентированного программирования Лекция 9. Пронципы объектно-ориентированного программирования
- •1. Основные понятия
- •2. Роль инкапсуляции
- •3. Роль наследования
- •4. Роль полиморфизма
- •Лекция 10-11. Классы и объекты
- •1. Основные понятия
- •2. Функциональные элементы класса
- •2.1. Данные: поля и константы
- •2.2. Методы
- •2.3. Конструкторы
- •2.4. Деструкторы
- •2.5. Свойства
- •2.6. Индексаторы
- •3. «Один класс – один файл»
- •Лекция 12-13. Класы коллекций
- •1. Основные понятия
- •2. Класс Stack
- •3. Класс Queue
- •4. Класс ArrayList
- •Тема 4. Инкапсуляция и скрытие информации Лекция 14. Инкапсуляция как средство структурирования систем
- •1. Основные понятия
- •2. Основная концепция инкапсуляции
- •Тема 5. Перегрузка операторов и функций Лекция 15. Модификатор доступа переменных и функций
- •1. Основные понятия
- •2. Примеры использования модификаторов доступа
- •Лекция 16. Перегрузка операторов и функций
- •1. Операции класса
- •2. Унарные операции
- •3. Бинарные операции
- •4. Операции преобразования типов
- •Implicit operator целевой_тип (параметр) //неявное преобразование
- •Тема 6. Наследование и полное использование кода Лекция 17. Основы наследования
- •1. Иерархия классов
- •2. Основы наследования
- •3. Использование защищенного доступа
- •Лекция 18. Вызов базового конструктора
- •1. Наследование конструкторов
- •2. Вызов базового конструктора
- •Тема 7. Многоуровневое наследование. Конфликт имен и потоков классов Лекция 19-20. Многоуровневое наследование и его недостатки
- •1. Многоуровневая иерархия
- •2. Переменные базового класса и производного класса
- •3. Виртуальные методы
- •4. Абстрактные методы и классы
- •Лекция 21. Классы потоков вводв и вывода
- •1. Основные понятия
- •2. Стандартный поток ввода
- •3. Стандартный поток вывода
- •4. Стандартный поток вывода сообщений об ошибках
- •5. Программа StdStreams
- •Лекция 22. Классы потоков для работы с файлами, памятью и сетью
- •1. Класс BufferedStream
- •2. Класс FileStream
- •3. Класс MemoryStream
- •4. Класс NetworkStream
- •5. Класс CryptoStream
- •Тема 8. Полиморфизм и виртуальные функции Лекция 23. Основы полиморфизма и преимущества его использования
- •1. Основы полиморфизма
- •2. Преимущества использования полиморфизма
- •Лекция 24. Динамическое связывание виртуальных методов
- •1. Виртуальные методы
- •2. Вызов базового метода
- •Тема 9. Интерфейсы Лекция 25. Интерфейсы
- •1. Основные понятия
- •2. Пример опредиления интерфейса и работы с ним
- •Лекция 26. Стандартные интерфейсы .Net
- •1. Стандартный интерфейс iComparable
- •2. Перегрузка операций отношения с помощью метода CompareTo
- •3. Стандартные интерфейсы iEnumerable и iEnumerator
- •Тема 10. Объектно-ориентированное программирование Windows-приложений на основе WindowsForms Лекция 27-28. Библиотеки классов реализации функциональных возможностей Windows
- •1. Формы
- •6. Компиляция программы
- •7. События в Windows-приложениях
- •7.1. События мыши
- •Лекция 29. Разработка графических интерфейсов пользователя
- •1. Общтие сведения
- •2. Группы элементов управления
- •Лекция 30-31. Работа с даннями
- •1. Что такое реляционная база данных?
- •2. Модель объектов ado.Net
- •3. Подготовка ado.Net к работе в приложении
- •Лекция 32. Создание пакетов установки
- •1. Общие сведения
- •2. Создание пакетов установки
- •3.Создание простого пакета установки без библиотеки .Net Framework
Тема 8. Полиморфизм и виртуальные функции Лекция 23. Основы полиморфизма и преимущества его использования
План:
Основы полиморфизма
Преимущества использования полиморфизма
1. Основы полиморфизма
Использование наследования часто приводит к созданию нескольких производных от данного базового классов. Например, мы можем определить несколько производных классов от класса Student. Важной способностью любого студента является способность сдавать экзамен. Допустим, что студенты младших курсов сдают экзамен путем сдачи серии учебных модулей, в результате чего окончательная оценка накапливается как результат оценок по каждому модулю. Студенты старшекурсники сдают «классический» экзамен – в конце учебного периода. Несмотря на разницу в способах сдачи экзаменов, во многих ситуациях управления студентами не хотелось бы постоянно учитывать описанное различие. Приведем программную реализацию данной ситуации.
class Student
{
private string name;
private int mark;
public Student(string n) { name = n; }
public void PassExam() { mark = 0; }
public string Name { get { return name; } }
public int Mark
{
get { return mark; }
set { mark = value; }
}
}
class YoungStudent : Student
{
private int[] modMarks;
private static Random r=new Random();
public YoungStudent(string n, int modCount): base(n)
{ modMarks = new int[modCount]; }
private void passModule(int n)
{ modMarks[n] = r.Next(0, 13); }
public void PassExam()
{
double d, s = 0.0;
for (int i = 0; i < modMarks.Length; i++)
{ passModule(i); s += modMarks[i]; }
d = s / modMarks.Length;
Mark = (int)(Math.Round(d));
}
}
class OldStudent : Student
{
private static Random r=new Random();
public OldStudent(string n) : base(n) { }
public void PassExam() { Mark = r.Next(0, 13); }
}
Класс Student сам по себе для создания объектов использоваться не будет. Поэтому он содержит сугубо формальную реализацию метода PassExam. Однако другие его методы будут успешно использоваться объектами производных классов без переопределения.
Далее в клиентской части (класс Program) мы решаем следующие задачи:
Создание множества студентов. Студенты двух типов помещаются в ArrayList.
Все созданные студенты сдают экзамен.
Выводится статистика оценок по всем студентам.
class Program
{
private static ArrayList students;
static void MakeStudents()
{
students = new ArrayList();
students.Add(new YoungStudent("Peter",2));
students.Add(new OldStudent("Terry"));
students.Add(new YoungStudent("Frank",2));
students.Add(new OldStudent("Ann"));
}
static void PassExams()
{
foreach (Student student in students)
{
switch (student.GetType().Name)
{
case "YoungStudent":
{((YoungStudent)student).PassExam(); break;}
case "OldStudent":
{((OldStudent)student).PassExam(); break;}
}
}
}
static void Report()
{
foreach (Student st in students)
Console.WriteLine("Student {0} has mark {1}", st.Name, st.Mark);
}
static void Main()
{
MakeStudents();
PassExams();
Report();
}
}
Ключевым моментом этой программы является реализация метода PassExam. Идеальным по простоте был бы следующий его вариант:
static void PassExams()
{
foreach (Student student in students) student.PassExam();
}
К сожалению, в таком случае все студенты получили бы оценку 0, поскольку для всех студентов в этом случае работает метод PassExam из базового класса. Дело в том, что решение о том, какой вариант метода PassExam вызывать принимается на стадии компиляции (это называется ранним связыванием) на основании типа объекта. А в приведенной реализации переменная цикла student описана базовым классом Student.
В результате приходится использовать средства для работы с информацией о типах во время выполнения программы (Run Time Type Information – RTTI). Основным средством этой категории является метод GetType, возвращающий информацию о типе объекта, на который ссылается переменная во время выполнения программы. Конструкция student.GetType().Name возвращает строку с именем этого типа. Такое решение не только громоздко, но и не надежно. Представьте, как тяжело будет поддерживать правильность такого программного кода, если:
1. Будут возникать все новые производные классы студентов.
2. Подобные методы, основанные на switch-анализе вариантов, встречаются во многих местах программы.
Данная проблема является типичной для объектно-ориентированного способа разработки программ и имеет свое решение. Разработчикам ОО языков удалось предложить средства, обеспечивающие позднее связывание, которое и известно под названием полиморфизма.
Полиморфная реализация метода PassExam потребует следующих шагов:
1. В базовом классе описать метод с ключевым словом virtual (виртуальный метод):
class Student
{ . . . public virtual void PassExam() { mark=0;} . . . }
2. В производных классах описать метод с ключевым словом override (переопределенный метод):
class YoungStudent : Student
{ . . .
public override void PassExam() { . . .}
. .
}
class OldStudent : Student
{ . . .
public override void PassExam() { . . .}
. .
}
Теперь метод PassExam выглядит просто:
static void PassExams()
{
foreach (Student st in students) st.PassExam();
}
Теперь решение о том, какой из методов PassExam вызывать откладывается на стадию выполнения программы и зависит не от «статического» типа переменной student, а от ее «динамического» типа, то есть от реального типа объекта, на который ссылается переменная в тот или иной момент выполнения программы.
Термин «полиморфизм» означает возможность разнотипных объектов самостоятельно продемонстрировать различие в своем поведении без выяснения типа этих объектов извне.
Поля не могут быть виртуальными. Виртуальными могут быть только методы, свойства и события.
