Ответ
Виртуальные методы — это механизм поддержки полиморфизма в C#, позволяющий производному классу предоставить свою собственную реализацию метода, уже определенного в базовом классе. Выбор конкретной реализации происходит во время выполнения (позднее связывание) на основе фактического типа объекта.
Как это работает?
- В базовом классе метод помечается ключевым словом
virtual. - В производном классе метод переопределяется с помощью ключевого слова
override. - При вызове метода у ссылки типа базового класса, которая ссылается на объект производного класса, будет выполнена переопределенная версия.
Практический пример:
public class NotificationSender
{
// Виртуальный метод с реализацией по умолчанию
public virtual void Send(string message)
{
Console.WriteLine($"[Base Sender] Отправка базового уведомления: {message}");
}
// Невиртуальный метод. Его нельзя переопределить, можно только скрыть (new).
public void Log(string action)
{
Console.WriteLine($"[Base Log] Действие: {action}");
}
}
public class EmailSender : NotificationSender
{
// Переопределение виртуального метода
public override void Send(string message)
{
// Можно вызвать базовую реализацию, если нужно
// base.Send(message);
Console.WriteLine($"[Email] Отправлено на email: {message}");
}
}
public class SmsSender : NotificationSender
{
public override void Send(string message)
{
Console.WriteLine($"[SMS] Отправлено SMS: {message}");
}
// Скрытие (shadowing) метода базового класса, а не переопределение.
public new void Log(string action)
{
Console.WriteLine($"[SMS Log] {action}");
}
}
// Использование:
NotificationSender sender1 = new EmailSender();
NotificationSender sender2 = new SmsSender();
NotificationSender sender3 = new NotificationSender();
// Полиморфный вызов. Реализация определяется реальным типом объекта.
sender1.Send("Заказ создан"); // Вывод: [Email] Отправлено на email: Заказ создан
sender2.Send("Заказ создан"); // Вывод: [SMS] Отправлено SMS: Заказ создан
sender3.Send("Заказ создан"); // Вывод: [Base Sender] Отправка базового уведомления: Заказ создан
// Важно: для невиртуальных методов вызов определяется типом ссылки.
sender2.Log("test"); // Вывод: [Base Log] Действие: test (т.к. ссылка типа NotificationSender)
((SmsSender)sender2).Log("test"); // Вывод: [SMS Log] test
Ключевые отличия virtual/override от new: |
Аспект | virtual / override |
new (скрытие) |
|---|---|---|---|
| Связывание | Позднее (runtime) | Раннее (compile-time) | |
| Полиморфизм | Поддерживает | Не поддерживает | |
| Вызов через ссылку базового класса | Вызывается метод производного класса | Вызывается метод базового класса |
Зачем это нужно? Виртуальные методы — основа для реализации шаблонов проектирования (например, Template Method), создания расширяемых библиотек и фреймворков, где поведение базовых классов должно настраиваться наследниками.