Ответ
Переопределение (override) в C# — это механизм, позволяющий производному классу предоставить свою собственную реализацию виртуального или абстрактного метода, объявленного в базовом классе. Реализация основана на таблице виртуальных методов (Virtual Method Table, VMT).
Синтаксис и правила:
public class LoggerBase
{
// 1. Метод должен быть помечен как virtual, abstract или уже override
public virtual void Log(string message)
{
Console.WriteLine($"[BASE] {DateTime.Now}: {message}");
}
}
public class FileLogger : LoggerBase
{
// 2. Сигнатура метода (имя, тип возвращаемого значения, параметры) должна полностью совпадать
// 3. Модификатор доступа должен быть таким же или менее строгим
public override void Log(string message)
{
// 4. Можно обратиться к реализации базового класса через base
base.Log(message); // Вызовет LoggerBase.Log
// Новая логика для записи в файл
File.AppendAllText("log.txt", message + "n");
}
}
Что происходит под капотом?
- Класс
LoggerBaseимеет в своей VMT запись, указывающую на реализациюLoggerBase.Log. - Класс
FileLoggerсоздаёт свою VMT. Для методаLogзапись указывает на новую реализацию (FileLogger.Log). - При вызове
logger.Log(...)гдеloggerимеет типLoggerBase, но ссылается на объектFileLogger, CLR смотрит в VMT реального типа объекта (FileLogger) и вызывает соответствующую реализацию. Это и есть полиморфизм.
Отличия от сокрытия (new):
public class A { public void Method() => Console.WriteLine("A"); }
public class B : A { public new void Method() => Console.WriteLine("B"); } // Сокрытие
A obj = new B();
obj.Method(); // Выведет "A"! Выбор метода определяется типом переменной (A), а не объекта.
((B)obj).Method(); // Выведет "B"
Ключевые моменты:
sealed override— запрещает дальнейшее переопределение метода в цепочке наследования.- Переопределять можно только виртуальные члены. Попытка переопределить невиртуальный метод приведёт к ошибке компиляции.
- Свойства и индексаторы также могут быть виртуальными и переопределяемыми.