Эрта боғланишда бажариш учун тайёр дастур бажарилиши мантиқи қатъий аниқланган структуралан иборат бўлади. Агар шажарадаги турли объектларнинг қайси бир хил номдаги методларидан фойдаланиш ҳақидаги карор метод қўлланадиган конкрет объектга боғлиқ равишда қабул қилинган бўлса, у холда бу методларни коднинг колган қисми билан олдиндан қатъий боғлаш мумкин эмас.
Демак, қандайдир усул билан компиляторга бу методларни бошқача усул билан қайта ишланиши кераклиги ҳақида хабар бериш лозим. Бунинг учун C# дастурлаш тилида virtual хизматчи сўзи киритилган. Бу базавий синф сарлавҳасида ёзилади: масалан:
virtual public void Passport() …
Методни виртуал деб эълон қилиш бу методга бўлган барча ҳаволаларни дастурнинг бажарилиш вақтида уларга мурожаат вақтида аниқ бўлишини англатади. Бу механизмни кечки боғланиш деб аталади.
Уни амалга ошириш учун виртуал методларнинг манзиллари номдан иҳтиёрий вақт мобайнида фойдаланиш мумкин бўлган жойда сақланиши шарт. Шунинг учун компилятор бу методлар учун виртуал методлар жадвали (Virtual Method Table, VMT) ни ташкил қилади. Унга барча виртуал методларнинг (шу жумладан ворислик асосида қабул қилинганлари хам) манзиллари синф тавсифида кўрсатилган тартибда ёзилади. Ҳар бир синф учун алоҳид жадвал ташкил қилинади.
Ҳар бир объект дастурнинг бажарилиш вақтида VMT билан ишлаш имкониятига эга бўлиши зарур. Объект экземплярининг VMT билан алоқаси компилятор томнидан тўғридан – тўғри объектнинг конструкторига жойланадиган махсус код ёрдамида ўрнатилади.
Ҳосила синфда виртуал методни қайта ишлаш учун override хизматчи сўзидан фойдаланиш мумкин, масалан:
override public void Passport() ...
Қайта аниқланган виртуал метод базавий синфдаги номдош метод билан бир хилдаги параметрларга эга бўлиши керак.
21.2.2-листингга иккита хизматчи сўзларни қўшамиз: virtual хамда override.
using System;
namespace ConsoleApplication1
{
class Monster
{
...
virtual public void Passport()
{
Console.WriteLine( "Monster {0} \t health = {1} ammo = {2}",
name, health, ammo );
}
...
}
class Daemon : Monster
{
...
override public void Passport()
{
Console.WriteLine(
"Daemon {0} \t health = {1} ammo = {2} brain = {3}",
Name, Health, Ammo, brain );
}
...
}
class Class1
{ static void Main()
{
const int n = 3;
Monster[] stado = new Monster[n];
stado[0] = new Monster( "Monia" );
stado[1] = new Monster( "Monk" );
stado[2] = new Daemon ( "Dimon", 3 );
foreach ( Monster elem in stado ) elem.Passport();
for ( int i = 0; i < n; ++i ) stado[i].Ammo = 0;
Console.WriteLine();
foreach ( Monster elem in stado ) elem.Passport();
}
}
}
21.2.3-листинг. Виртуал методлар
Дастурнинг натижаси қуйидагича:
Monster Monia health = 100 ammo = 100
Monster Monk health = 100 ammo = 100
Daemon Dimon health = 100 ammo = 100 brain = 3
Monster Monia health = 100 ammo = 0
Monster Monk health = 100 ammo = 0
Daemon Dimon health = 100 ammo = 0 brain = 3
Теперь в циклах 1 и 3 вызывается метод Passport, соответствующий типу объекта, помещенного в массив.
Виртуальные методлар базового синфа определяют интерфейс всей иерархии. Этот интерфейс может расширяться в потомках за счет добавления новых виртуальных методов. Переопределять виртуальный метод в каждом из потомков не обязательно: агар он выполняет устраивающие потомка действия, метод наследуется.
С помощью виртуальных методов реализуется один из основных принципов объектно-ориентированного программирования — полиморфизм. Это слово в переводе с греческого означает "много форм", что в данном случае означает "один вызов — много методов".
Виртуальные методлар незаменимлар и при передаче объектов в методлар в качестве параметров. В параметрах метода описывается объект базового типа, а при вызове в нее передается объект производного синфа. Виртуальные методлар вызываемые для объекта из метода, будут соответствовать типу аргумента, а не параметра.
Do'stlaringiz bilan baham: |