Метод объявляется как виртуальный в базовом классе с помощью ключевого слова 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
.