|
Программирование >> Обработка исключительных ситуаций
Результат работы программы: 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, соответствующий типу объекта, помещенного в массив. Виртуальные методы базового класса определяют интерфейс всей иерархии. Этот интерфейс может расширяться в потомках за счет добавления новых виртуальных методов. Переопределять виртуальный метод в каждом из потомков не обязательно: если он выполняет устраивающие потомка действия, метод наследуется. Вызов виртуального метода выполняется так: из объекта берется адрес его таблицы VMT, из VMT выбирается адрес метода, а затем управление передается этому методу. Таким образом, при использовании виртуальных методов из всех одноименных методов иерархии всегда выбирается тот, который соответствует фактическому типу вызвавшего его объекта. ПРИМЕЧАНИЕ- Вызов виртуального метода, в отличие от обычного, выполняется через дополнительный этап получения адреса метода из таблицы VMT , что несколько замедляет выполнение программы. С помощью виртуальных методов реализуется один из основных принципов объектно-ориентированного программирования - полиморфизм. Это слово в переводе с греческого означает много форм , что в данном случае означает один вызов - много методов . Применение виртуальных методов обеспечивает гибкость и возможность расширения функциональности класса. Виртуальные методы незаменимы и при передаче объектов в методы в качестве параметров. В параметрах метода описывается объект базового типа, а при вызове в нее передается объект производного класса. В этом случае виртуальные методы, вызываемые для объекта из метода, будут соответствовать типу аргумента, а не параметра. При описании классов рекомендуется определять в качестве виртуальных те методы, которые в производных классах должны реализовываться по-другому. Если во всех классах иерархии метод будет выполняться одинаково, его лучше определить как обычный метод. ПРИМЕЧАНИЕ- Все сказанное о виртуальных методах относится также к свойствам и индексаторам. Абстрактные классы 181 Абстрактные классы При создании иерархии объектов для исключения повторяющегося кода часто бывает логично выделить их общие свойства в один родительский класс. При этом может оказаться, что создавать экземпляры такого класса не имеет смысла, потому что никакие реальные объекты им не соответствуют. Такие классы называют абстрактными. Абстрактный класс служит только для порождения потомков. Как правило, в нем задается набор методов, которые каждый из потомков будет реализовывать по-своему. Абстрактные классы предназначены для представления общих понятий, которые предполагается конкретизировать в производных классах. Абстрактный класс задает интерфейс для всей иерархии, при этом методам класса может не соответствовать никаких конкретных действий. В этом случае методы имеют пустое тело и объявляются со спецификатором abstract. ПРИМЕЧАНИЕ- Абстрактный класс может содержать и полностью определенные методы, в отличие от сходного с ним по предназначению специального вида класса, называемого интерфейсом. Интерфейсы рассматриваются в следующей главе. Если в классе есть хотя бы один абстрактный метод, весь класс также должен быть описан как абстрактный, например: abstract class Spirit public abstract void PassportO: class Monster : Spirit { override public void PassportO Console.Writel ine( Monster {0} \t health = {1} ammo = {2} , name, health, ammo ); class Daemon : Monster { override public void PassportO Console. Writeline( Daemon {0} \t health = {1} ammo = {2} brain = {3} , Name, Health, Ammo, brain ); ... полный текст этих классов приведен в главе 12 Бесплодные классы В С# есть ключевое слово sealed, позволяющее описать класс, от которого, в противоположность абстрактному, наследовать запрещается: sealed class Spirit i class Monster : Spirit { ... } ошибка! Большинство встроенных типов данных описано как sealed. Если необходимо использовать функциональность бесплодного класса, применяется не наследование, а вложение, или включение: в классе описывается поле соответствующего типа. Вложение классов, когда один класс включает в себя поля, являющиеся классами, является альтернативой наследованию при проектировании. Например, если есть объект двигатель , а требуется описать объект самолет , логично сделать двигатель полем этого объекта, а не его предком. Поскольку поля класса обычно закрыты, возникает вопрос, как же пользоваться методами включенного объекта. Общепринятый способ состоит в том, чтобы описать метод объемлющего класса, из которого вызвать метод включенного класса. Такой способ взаимоотношений классов известен как модель включения-делегирования. Пример приведен в листинге 8.4. Листинг 8.4. Модель включения-делегирования using System; namespace ConsoleApplicationi class Двигатель { public void Запуске) Абстрактные классы используются при работе со структурами данных, предназначенными для хранения объектов одной иерархии, и в качестве параметров методов. Если класс, производный от абстрактного, не переопределяет все абстрактные методы, он также должен описываться как абстрактный. Можно создать метод, параметром которого является абстрактный класс. На место этого параметра при выполнении программы может передаваться объект любого производного класса. Это позволяет создавать полиморфные методы, работающие с объектом любого типа в пределах одной иерархии. Полиморфизм в различных формах является мощным и широко применяемым инструментом ООП. ПРИМЕЧАНИЕ- Мы уже использовали полиморфизм в разделе Оператор foreach (см. с. 136) для того, чтобы метод PrintArray мог работать с массивом любого типа. Еще один пример применения абстрактных и виртуальных методов имеется в главе 10.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |