Я завершила экзамен 90 баллов на 5. Сертификат не заказала. Сейчас пытаюсь найти как его заказать. у меня указано экзамен пройден баллы оценка видно, а чтоб заказать сертификат нигде не видно. |
Иерархии объектов. Работа с объектами в динамической памяти
Наследование
Презентацию к данной работе Вы можете скачать здесь.
Управлять большим количеством разрозненных объектов достаточно сложно. С этой проблемой можно справиться путем упорядочивания и ранжирования объектов, то есть объединяя общие для нескольких объектов свойства в одном объекте и используя этот объект в качестве базового.
Эту возможность предоставляет механизм наследования. Он позволяет строить иерархии, в которых объекты-потомки получают свойства объектов-предков и могут дополнять их или изменять. Таким образом, наследование обеспечивает возможность повторного использования кода.
Объекты, расположенные ближе к началу иерархии, объединяют в себе наиболее общие черты для всех нижележащих объектов. По мере продвижения вниз по иерархии объекты приобретают все больше конкретных особенностей.
Объект в Паскале может иметь произвольное количество потомков и только одного предка. При описании объекта имя его предка записывается в круглых скобках после ключевого слова object.
Допустим, нам требуется ввести в игру еще один тип персонажей, который должен обладать свойствами объекта monster, но по-другому выглядеть и атаковать. Будет логично сделать новый объект потомком объекта monster. Проанализировав код методов этого объекта, переопределим только те, которые реализуются по-другому ( пример 7.1).
type daemon = object (monster) procedure init(x_, y_, health_, ammo_, magic_ : word); procedure attack; procedure draw; procedure erase; procedure wizardry; private magic : word; end; { ------------------------- реализация методов объекта daemon ----------------- } procedure daemon.init(x_, y_, health_, ammo_, magic_ : word); begin inherited init(x_, y_, health_, ammo_); color := green; magic := magic_; end; procedure daemon.attack; { --------------------------------- daemon.attack ---- } begin if ammo = 0 then exit; dec(ammo); if magic > 0 then begin outtextXY(x + 15, y, 'БУ-БУХ!'); dec(magic); end else outtextXY(x + 15, y, 'бу-бух!'); end; procedure daemon.draw; { ----------------------------------- daemon.draw ---- } begin setcolor(color); outtextXY(x, y, '%)'); end; procedure daemon.erase; { ----------------------------------- daemon.erase ---- } begin setcolor(black); outtextXY(x, y, '%)'); end; procedure daemon.wizardry; { -------------------------------- daemon.wizardry - } begin if magic = 0 then exit; outtextXY(x + 15, y, 'крибле-крабле-бумс!'); dec(magic); end;Листинг 7.1. Переопределение методов после добавления нового типа персонажей
Наследование полей.Унаследованные поля доступны в объекте точно так же, как и его собственные. Изменить или удалить поле при наследовании нельзя.Объект daemon содержит все поля своего предка и одно собственное поле magic, в котором хранится "магическая сила" объекта.
Наследование методов.В потомке объекта можно не только описывать новые методы, но и переопределять существующие. Метод можно переопределить либо полностью, либо дополнив метод предка.
В объекте daemon описан новый метод wizardry, с помощью которого объект применяет свою магическую силу, а метод инициализации init переопределен, потому что количество полей объекта изменилось. Однако необходимость задавать значения унаследованным полям осталась, и соответствующий метод есть в объекте monster, поэтому из нового метода инициализации сначала вызывается старый, а затем выполняются дополнительные действия (присваивание значения полю ammo ).
Вызов метода предка из метода потомка выполняется с помощью ключевого слова inherited (унаследованный). Можно вызвать метод предка и явным образом с помощью конструкции monster.init.
Методы отрисовки draw и erase также переопределены, потому что изображение демона отличается от изображения монстра и, следовательно, формируется другой последовательностью подпрограмм (для простоты представим демона в виде "смайлика").
Переопределен и метод attack: теперь атака выполняется по-разному в зависимости от наличия магической силы.
Чтобы перемещать демона, требуется выполнить те же действия, что записаны в методе move для перемещения монстра: необходимо стереть его изображение на старом месте, обновить координаты и нарисовать на новом месте. На первый взгляд, можно без проблем унаследовать этот метод, а также метод hit. Так мы и поступим.
Добавим описание объекта daemon в интерфейсную часть модуля monsters, а тексты его методов — в раздел реализации. Проверим работу новых методов с помощью программы:
program test_inheritance; uses graph, crt, monsters; var Vasia : daemon; gd, gm : integer; begin gd := detect; initgraph(gd, gm, '...'); if graphresult <> grOk then begin writeln('ошибка инициализации графики'); exit end; Vasia.init(100, 100, 20, 10, 6); Vasia.draw; Vasia.attack; readln; Vasia.erase; readln; end.
И в предке, и в потомке есть одноименные методы. Вызывается всегда тот метод, который соответствует типу объекта, потому что при вызове указывается имя экземпляра заданного типа ( рис. 7.1). Это можно рассматривать как простейший вид полиморфизма.