Метод объявляется как виртуальный в базовом классе с помощью ключевого слова virtual, указываемого перед его именем. Когда же виртуальный метод переопределяется в производном классе, то для этого используется модификатор override. А сам процесс повторного определения виртуального метода в производном классе называется static или abstract (подробнее данный вопрос рассматривается далее в этой главе).
Переопределение метода служит основанием для воплощения одного из самых эффективных в C# принципов:
Ниже приведен пример, демонстрирующий виртуальные методы и их переопределение.
// Продемонстрировать виртуальный метод.
using System;
class Base {
// Создать виртуальный метод в базовом классе,
public virtual void Who() {
Console.WriteLine("Метод Who() в классе Base");
}
}
class Derived1 : Base {
// Переопределить метод Who() в производном классе,
public override void Who() {
Console.WriteLine("Метод Who() в классе Derivedl");
}
}
class Derived2 : Base {
// Вновь переопределить метод Who() в
//еще одном производном классе,
public override void Who() {
Console.WriteLine("Метод Who() в классе Derived2");
}
}
class OverrideDemo {
static void Main() {
Base baseOb = new Base();
Derived1 dObl = new Derived1();
Derived2 dOb2 = new Derived2();
Base baseRef; // ссылка на базовый класс
baseRef = baseOb;
baseRef.Who() ;
baseRef = dObl;
baseRef.Who();
baseRef = dOb2;
baseRef.Who();
}
}
Вот к какому результату приводит выполнение этого кода.
Метод Who() в классе Base.
Метод Who() в классе Derived1
Метод Who() в классе Derived2
В коде из приведенного выше примера создаются базовый класс Base и два производных от него класса — Derived1 и Derived2. В классе Base объявляется виртуальный метод Who(), который переопределяется в обоих производных классах. Затем в методе Main() объявляются объекты типа Base, Derivedl и Derived2. Кроме того, объявляется переменная baseRef ссылочного типа Base. Далее ссылка на каждый тип объекта присваивается переменной baseRef и затем используется для вызова метода Who(). Как следует из результата выполнения приведенного выше кода, вариант выполняемого метода Who() определяется по типу объекта, к которому происходит обращение по ссылке во время вызова этого метода, а не по типу класса переменной baseRef.