C#. Виртуальные и невиртуальные методы. Статические методы.



Виртуальные методы и их переопределение

Виртуальным называется метод, объявляемый с помощью ключевого сова

v i r t u a l в базовом классе и переопределяемый в одном или нескольких производных классах. Таким образом, каждый производный класс может иметь собственную версию виртуального метода. Виртуальные методы представляют интерес с такой позиции: что произойдет, если виртуальный метод будет вызван посредством ссылки на базовый класс. Какую именно версию метода нужно вызвать, С# определяет по типу объекта, на который указывает эта ссылка, причем решение принимается динамически, во время выполнения программы. Следовательно, если имеются ссылки на различные объекты, будут выполняться различные версии виртуального метода. Другими словами, именно тип объекта, на который указывает ссылка (а не тип ссылки) определяет, какая версия виртуального метода будет выполнена. Таким образом, если базовый класс содержит виртуальный метод и из этого класса выведены производные классы, то при наличии ссылки на различные типы объектов (посредством ссылки на базовый класс) будут выполняться различные версии этого виртуального метода.

Чтобы объявить метод в базовом классе виртуальным, его объявление необходимо предварить ключевым словом v i r t u a l . При переопределении виртуального метода в производном классе используется модификатор override. Итак, процесс переопределения виртуального метода в производном классе иногда называется замещением метода (method overriding). При переопределении метода сигнатуры типа у виртуального и метода-заменителя должны совпадать. Кроме того, виртуальный метод нельзя определять как статический (с использованием слова s t a t i c ) или абстрактный (с использованием слова a b s t r a c t , о котором пойдет речь ниже в этой главе).

Переопределение виртуального метода формирует базу для одной из самых мощных концепций С#: динамической диспетчеризации методов. Динамическая диспетчеризация методов — это механизм вызова переопределенного метода во время выполнения программы, а не в период компиляции. Именно благодаря механизму диспетчеризации методов в С# реализуется динамический полиморфизм.

Рассмотрим пример, который иллюстрирует виртуальные методы и их переопреде-

ление.

// Демонстрация виртуального метода.

using System; i

class Base {

// Создаем виртуальный метод в базовом классе,

public virtual void who () {

Console.WriteLine("Метод who() в классе Base.");

class Derivedl : Base {

// Переопределяем метод who() в производном классе,

public override void who() {

Console.WriteLine("Метод who() в классе Derivedl")

class Derived2 : Base {

// Снова переопределяем метод who()

// в другом производном классе,

public override void who() {

Console.WriteLine("Метод who() в классе Derived2

class OverrideDemo {

public static void Main() {

Base baseOb = new Base();

Derivedl dObl = new Derivedl()

Derived2 dOb2 = new Derived2()

Base baseRef; // Ссылка на базовый класс.

baseRef = baseOb;

baseRef.who();

baseRef = dObl; ч

baseRef.who() ;

baseRef = dOb2;

baseRef.who() ;

Вот результаты выполнения этой программы: IМетод who() в классе Base.

Метод who() в классе Derivedl

Метод who() в классе Derived2

В программе создается базовый класс Base и два производных класса — Derivedl

и Derived2. В классе Base объявляется метод с именем who (), а производные классы

его переопределяют. В методе Main() объявляются объекты типа Base, Derivedl и

Derived2, а также ссылка baseRef типа Base. Затем программа поочередно присваи-

вает ссылку на объект каждого типа ссылке baseRef и использует эту ссылку для вы-

зова метода who (). Как показывают результаты выполнения этой программы, нужная

для выполнения версия определяется типом объекта, адресуемого в момент вызова, а

не "классовым" типом ссылки baseRef.

Виртуальный метод переопределять необязательно. Если производный класс не

предоставляет собственную версию виртуального метода, используется версия, опре-

деленная в базовом классе. Вот пример:

/* Если виртуальный метод не переопределен

в производном классе, используется метод

базового класса. Л/

using System;

class Base {

// Создаем виртуальный метод в базовом классе,

public virtual void who() {

Console.WriteLine("Метод who() в классе Base");

class Derivedl : Base {

// Переопределяем метод who() в производном классе,

public override void who() {

Console.WriteLine("Метод who() в классе Derivedl");

class Derived2 : Base {

// Этот класс не переопределяет метод who().

}

class NoOverrideDemo {

public static void Main() {

Base baseOb = new Base();

Derivedl dObl = new Derivedl();

Derived2 dOb2 = new Derived2();

Base baseRef; // Ссылка на базовый класс.

baseRef = baseOb;

baseRef.who(); ,

baseRef = dObl;

baseRef.who();

baseRef = dOb2;

baseRef.who(); // Вызывает метод who() класса Base.

Вот результаты выполнения этой программы:

Метод who() в классе Base

Метод who() в классе Derivedl

Метод who() в классе Base


Дата добавления: 2018-05-13; просмотров: 1189; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!