|
Программирование >> Обработка исключительных ситуаций
Виртуальные методы При раннем связывании программа, готовая для выполнения, представляет собой структуру, логика выполнения которой жестко определена. Если же требуется, чтобы решение о том, какой из одноименных методов разных объектов иерархии использовать, принималось в зависимости от конкретного обьекта, для которого выполняется вызов, то заранее жестко связывать эти методы с остальной частью кода нельзя. Следовательно, надо каким-то образом дать знать компилятору, что эти методы будут обрабатываться по-другому. Для этого в С# существует ключевое слово virtual. Оно записывается в заголовке метода базового класса, например: virtual public void Passport!) Слово virtual в переводе с английского значит фактический . Объявление метода виртуальным означает, что все ссылки на этот метод будут разрешаться по факту его вызова, то есть не на стадии компиляции, а во время выполнения программы. Этот механизм называется поздним связыванием. Для его реализации необходимо, чтобы адреса виртуальных методов хранились там, где ими можно будет в любой момент воспользоваться, поэтому компилятор формирует для этих методов таблицу виртуальных методов (Virtual Method Table. VMT) . В нее записываются адреса виртуальных методов (в том числе унаследованных) в порядке описания в классе. Для каждого класса создается одна таблица. Каждый объект во время выполнения должен иметь доступ к VMT. Обеспечение этой связи нельзя поручить компилятору, так как она должна устанавливаться во время выполнения программы при создании объекта. Поэтому связь экземпляра объекта с VMT устанавливается с помощью специального кода, автоматически помещаемого компилятором в конструктор объекта. Если в производном классе требуется переопределить виртуальный метод, используется ключевое слово override, например: override public void PassportO ... Переопределенный виртуальный метод должен обладать таким же набором параметров, как и одноименный метод базового кчасса. Это требование вполне естественно, если учесть, что одноименные методы, относящиеся к разным классам, могут вызываться из одной и той же точки программы. моменты времени могут находиться ссылки на объекты разных типов, компилятор учесть не может. Следовательно, если мы хотим, чтобы вызываемые методы соответствовали типу объекта, необходимо отложить процесс связывания до этапа выполнения программы, а точнее - до момента вызова метода, когда уже точно известно, на объект какого типа указывает ссылка. Такой механизм в С# есть - он называется поздним связыванием и реализуется с помощью так называемых виртуальных методов, которые мы незамедлительно и рассмотрим. Виртуальные методы Добавим в листинг 8.2 два волшебных слова - virtual и override - в описания методов Passport, соответственно, базового и производного классов (листинг 8.3). Листинг 8.3. Виртуальные методы using System; namespace ConsoleApplicationi class Monster virtual public void PassportO Console.WriteLineC Monster {0} \t health = {1} ammo = {2} , name, health, ammo ); class Daemon ; Monster override public void PassportO Console.WriteLineC Daemon {0} \t health = {1} ammo = {2} brain = {3} , Name. Health, Ammio, brain ); class Classl static void MainO const int n = 3; Monster[] stado = new Monster[n]; stado[0] = new MonsterC Monia ); stado[l] = new MonsterC Monk ): stado[2] = new Daemon ( Dimon , 3 ); foreach ( Monster elem in stado ) elem.PassportO; for ( int i = 0; i < n; ++i ) stado[i].Ammo Console.WriteLineC): foreach ( Monster elem in stado ) elem.PassportO; соответствовать друг другу. Правила соответствия подробно рассматриваются в следующих разделах. Для каждого параметра должны задаваться его тип и имя. Например, заголовок метода Sin выглядит следующим образом: public static double Sin( double a ): Имя метода вкупе с количеством, типами и спецификаторами его параметров представляет собой сигнатуру метода - то, по чему один метод отличают от других. В классе не должно быть методов с одинаковыми сигнатурами. В листинге 5.2 в класс Demo добавлены методы установки и получения значения поля у (на самом деле для подобных целей используются не методы, а свойства, которые рассматриваются чуть позже). Кроме того, статическое поле s закрыто, то есть определено по умолчанию как private, а для его получения описан метод Gets, являющий собою пример статического метода. Листинг 5.2. Простейшие методы using System; namespace ConsoleApplicationl { class Demo pubic int э = 1 ; public const double с - 1.66; static string s = Demo ; double y; public double GetyO метод получения поля у return у; public void SetyC double y ) метод установки поля у У = У : public static string Gets О метод получения поля s return s; class Classl { static void MainO Demo x = new Demo(); x.Sety(0.12): вызов метода установки поля у
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |