
- •Тема 2.8. Виртуальные функции в c#
- •Что такое «Виртуальные функции»?
- •Как объявляются виртуальные функции?
- •Абстрактные функции и абстрактные классы
- •Модификатор sealed
- •Реализация виртуального механизма
- •Тема 2_09. Универсальные (параметризованные) классы. Шаблоны
- •Наследование и универсальность
- •Синтаксис универсального класса
- •Класс с универсальными методами
- •Два основных механизма объектной технологии
- •Ограниченная универсальность
- •Синтаксис ограничений
- •Framework .Net и универсальность
Тема 2.8. Виртуальные функции в c#
Что такое «Виртуальные функции»? 1
Как объявляются виртуальные функции? 4
Абстрактные функции и абстрактные классы 4
Модификатор sealed 6
Реализация виртуального механизма 7
Наследование и универсальность 7
Синтаксис универсального класса 8
Класс с универсальными методами 8
Два основных механизма объектной технологии 8
Ограниченная универсальность 12
Синтаксис ограничений 12
Родовое порождение класса 14
Универсальные структуры 14
Универсальные интерфейсы 14
Универсальные делегаты 14
Framework .Net и универсальность 15
В этой лекции рассматриваются приемы управления передачей свойств при наследовании.
С помощью модификаторов virtual, override, abstract и sealed можно разрешать или запрещать переопределение функций, делать переобъявление обязательным, запрещать использование родительских функций и производство наследников.
Что такое «Виртуальные функции»?
Это такие функции базового класса, которые могут переопределяться из дочернего класса. Когда в базовом классе идет обращение к виртуальной функции, на самом деле вызывается ее вариант из дочернего класса.
class Square
{ protected double x=10; // Сторона, (мм)
public void Print_S(){ Console.WriteLine("Площадь = {0:F3}", Area());}
protected virtual double Area(){ return x * x; }
}
class Rhumb : Square
{ double a=Math.PI/4; // Угол, (рад)
protected override double Area() { return x * x * Math.Sin(a); }
}
class Program
{ static void Main()
{ Rhumb r1 = new Rhumb();
r1.Print_S();
Console.ReadKey();
}
}
Зачем нужны виртуальные функции?
Без них невозможно строить иерархию классов с «отложенными на потом» действиями.
Например, в базовом классе «подвижный объект» из предыдущей лекции может быть определена функция NewPoz, которая определяет изменение положения объекта под действием силы. Для этого определение изменения положения нужно знать, сколько прошло времени и как за это время под действием силы изменилась скорость. Для этого служит функция того же базового класса VarSpeed, вычисляющая скорость объекта.
Однако на алгоритм вычисления скорости влияют особенности объектов: ограничения на пространство движения, учет массы груза. Поэтому функция VarSpeed должна переобъявляться практически в каждом дочернем классе. Если она не виртуальна, то и функцию NewPoz придется дублировать (переобъявлять) в каждом дочернем классе, чтобы каждая ее копия могла вызывать «свою» VarSpeed. Это неудобно, и нарушает принципы ООП.
Если сделать функцию VarSpeed виртуальной, то вместо переобъявления, которое скрывает родительский метод, можно сделать переопределение, т.е. обеспечить автоматическую подстановку новой функции вместо старой выше по иерархии.
В этом случае диаграмма классов станет несколько проще:
Как объявляются виртуальные функции?
Для этого перед ними в базовом классе ставится ключевое слово virtual. В дочерних классах ставится слово override.
Теперь функция NewPoz объявлена только в классе «движущийся объект» и нигде не дублируется. Поэтому при вычислении позиции некоторого объекта из класса «Грузовой автомобиль», вызов функции VarSpeed будет происходить по следующей схеме:
Примечание
Виртуальная функция не может быть закрытой (private).
Виртуальная функция не может быть статической (static).