Реклама:

procedure TTroll.Attack(obj: TLi feObj ect); begin

if DistanceTo(obj.AbsolutePosition)>100 then AttackAsMage(obj); (атакуем магией} else inherited Attack(obj); end;

Предполагается, что AttackAsMage уже реализован. Обратите внимание на ключевое слово inherited перед повторным вызовом метода Attack. Это не рекурсия, как вы могли подумать, т.е. метод не вызывает сам себя. Ключевое слово inherited указывает на то, что мы должны вызвать метод предка этого класса. Еще раз посмотрите на объявление метода Attack у класса TBattleCharacter и TTroll. Метод у TBattleCharacter помечен словом virtual, т.е. он виртуальный, его можно перегрузить. Метод у TTroll помечен словом override, что и обозначает перегрузку. Итак, все эти три ключевых слова: virtual, override и inherited позволяют организовать иерархическое дерево методов. Таким образом, с помощью иерархии классов мы можем дать объектам не только общие свойства, но и общие фрагменты кода, отвечающие за одинаковые действия.

Есть еще одно ключевое слово из этой же категории — abstract. Если его поставить после объявления метода, который вы собираетесь перегружать, для него вообще не нужна реализация. То есть, в классе будет только название метода, и больше ничего. Ну а его реализация или каскад реализаций вы сможете написать в классах-потомках.

У иерархической модели методов есть одно замечательное свойство, которое на первый взгляд, неочевидно. На деле же это один из удобнейших приемов в объектно-ориентированном программировании. Рассмотрим все тот же пример с троллем и ор-ком. Допустим, вы пишете искусственный интеллект для группы разных боевых существ. В какой-то момент игрок выделил рамкой свое могучее воинство и послал его в туманную даль бить врагов. В обычном случае вам придется для каждого существа в отряде вызывать метод Attack. Но так как эти существа принадлежат десяткам разных классов, вам придется повторить это действие для каждого типа существ в отдельности! А вот как этого же можно добиться с нашей системой. Предположим, что Creatures — это список всех существ нашего отряда.

For х:=1 to Creatures.Count do (Creatures[x] as TBattleCharacter).Attack(obj)

Всего одна строчка! Игра берет самый первый объект списка Creatures, приводит его к классу TBattleCharacter (мы имеем полное право так сделать, потому что все объекты нашего списка являются потомками TBattleCharacter в том или ином поколении), и для приведенного объекта вызываем метод Attack. Далее игра для каждого типа объектов проходит вверх по дереву его предков, доходит до него самого и вызывает его личный метод Attack. То есть, эта строчка вызовет разные методы Attack для тролля и орка. Каждому — свой. Мораль: тщательно планируйте иерархию классов, чтобы однотипный код перекрывался на разных уровнях дерева классов. Тогда с помощью нескольких строчек кода вы сможете сделать столько всего, на что при обычном подходе ушла бы не одна страница.

Перепишем всех!

Когда мы посылали все могучее виртуальное воинство на бой одной единственной строчкой, то использовали в ней список Creatures. В нем хранятся все игровые персонажи. Давайте разберемся, что это за звери такие — списки.


⇐ Предыдущая страница| |Следующая страница ⇒