Основы программирования (947332), страница 55
Текст из файла (страница 55)
V;BeginV:=^Square*height;{обращаемся к методу базового класса}End;VarA:TVRoom;BeginA.NewInit(3.4.5.l2.8);WriteLn(*nnoutadb комнаты = \A.Square:6:2);WriteLn(V6beM комнаты = ', A. V:6:2);EndРис. 11.3. Полякласса TVRoom328Класс TVRoom, таким образом, включает триполя: length, width и height (рис. 11.3) и четыре метода: Square, Init, Newlnit и V.
Все поля и методыдоступны как из методов производного класса, так" непосредственно из программы.IL Иерархии классовЕсли программа, работая с объектами класса-потомка, не использует некоторых методов родителя, то в исполняемую программу они не включаются.Примечание. По правилам Borland Pascal у класса может быть только один родитель, носколько угодно потомков. Поскольку каждый производный класс добавляет при наследованиисвои поля и методы, в иерархии классов по мере удаления от корня дерева иерархии сложность классов и соответственно обье1сгов, которые эти классы реализуют, возрастает.
Одновременно возрастает и специализация классов. Наиболее универсальные классы, таким образом, находятся у корня дерева классов.Операция присваивания объектов родственных классов. В BorlandPascal допустимо присваивание объектам класса-родителя значений объектов класса-потомка. Обратное присваивание не разрешено, так как при еговыполнении методом «поле за полем» собственные поля объекта класса-потомка окажутся не определенными.Например:VarA:TRoom;B:TVRoom;...А:-В;{допустимо}В:-А;... {недопустимо: ошибка!}Особенности работы с указателями на объекты родственных классов. По правилам Borland Pascal допустимо указателям на объекты классародителя присваивать адреса объектов класса-потомка.
Однако при этоуказателъ на объект базового класса не обеспечивает возможности обращения к полям и методам, объявленным в производном классе (рис. 11.4).Например:Указатель на объекткласса-родителяШаблон указателя наобъект класса-родителя"Невидимые** поляи методы объекта???Объект класса-потомкаРис. 11.4. Обращение к полям класса потомка черезуказатель на объекты класса-родителя329Часть 2. Объектно-ориентированное программированиеVarpC: ^TRoom;E.TVRoom;...{указатель на объекты базового класса}{объект производного класса}рС:- @Е;{присваиваем указателю на объекты базового класса адрес объекта производного класса}рС^.height: =2.7; {ошибка, указатель на объекты типа класса-родителя не подозревает о существовании поля heightкласса TVRoom}В этих случаях приходится явно переопределять тип указателя, используя имя типа указателя (см. параграф 2.5):Туре pTVRoom^'^TVRoom;VarpC: ^TRoom; {указатель на объекты базового класса}Е:TVRoom;...
{объект производного класса}рС:= @Е;{присваиваем указателю на объекты базового классаадрес объекта производного класса}pTVRoom(pC)^.height:=2.7; {явно переопределяем тип указателя}Задания для самопроверкиЗадание 1. Спроектируйте класс для реализации объекта «Окно», который, получив сообщение «Изобразить», должен выводить в определенное место экрана окно заданного размера и цвета. На базе класса, реализующего объект «Окно», спроектируйте класс для реализации объекта «Окно с текстом».
Объект должен уметь реагировать на сообщение «Изобразить окно и вывести в него строку текста». Разработайте тестирующую программу.Задание 2. Спроектируйте на базе класса, реализующего объект «Окно с текстом» предыдущего задания, класс, реализующий объект «Окно с текстом, меняющеецвет». Объекты данного класса должны уметь реагировать на сообщение «Изменитьцвет окна».11.2. КомпозицияКомпозицией называют способ конструирования классов, при котором встроящийся класс включают объекты других классов. Включение реализовано посредством использования объектных поПлощадь?лей - полей типа «класс».ТрехмернаяПример 11.2. Разработать класс для реаОбъем?комнатализации объекта Квартира, который долженреагировать на запрос о жилой площади кварРис.
11.5. Объект Квартира тиры (рис. 11.5).330//. Иерархии классовTRoomlength, widthSquare(), Init ()15TFlatn, roomsrTRoom^FlatSquare(), Init ()Рис. 11.6. Диафамма классов примераФизически любая квартира состоит из нескольких комнат. Ранее у насуже был разработан класс TRoom, который хранил данные о длине и ширине комнаты и «умел» реагировать на запрос о площади комнаты. Количествокомнат в квартире сравнительно не велико и всегда ограничено, для определенности будем считать, что реализуемый объект не может включать более15 комнат. Тогда разрабатываемый класс TFlat должен включать массив из 15объектов типа TRoom (рис.
11.6). Реальное количество комнат будем хранитьв поле п. Для ответа на запрос о площади добавим метод FlatSquare, которыйбудет обращаться к методам Square объектов-комнат TRoom.Для инициализации объектных полей будем передавать в инициализирующий метод специальный массив значений параметров. Поскольку размерность этого массива будет определяться реальным количеством комнат, а значит будет отличаться от размерности поля rooms, необходимо описать параметр как открытый массив или нетипизированный параметр.
Используемвторой вариант.Program ex;Uses Room;{модуль Room определен в параграфе 10.3}Туре TFlat=object {описание класса}n:byte;{количество комнат}rooms:array[L.15] of TRoom; {массив объектов TRoom}function FlatSquare:real;{MQTOJX определения площади}procedure Init(an:byte;Var arooms);{MQTOJX инициализации}end;Procedure TFlatJnit; {тело метода инициализации}Var a:array[L,15] of TRoom absolute arooms; {переопределение типамассива наложением - см. параграф 5.5}Ubyte;Beginп:='ап;{инициализируем поле количества комнат}for i:=l to п do {инициализируем объектные поля, вызывая методинициализации TRoom для каждой комнатыи передавая ему размеры комнат}rooms[i].Inlt(a[i].length, а[i],width);End;331Часть 2, Объектно-ориентированное программированиеFunction TFlaLFlatSquare; {тело метода определения площади}Var S:real;i: integer;BeginS:=0;for i:=l to n do {суммируем площади комнат}S: =S+rooms[iJ, Square;FlatSquare:=S;End;Const mas:array[L.3]of TRoom- ((length:!.5; width:3.75),(length:2.85; width:4.1),(length:2.3; width:2.8));Var F:TFlat; {объявляем объект-переменную}BeginFInit(3,mas);{инициализируем объект}WriteLn(*Площадь квартиры= \FFlatSquare);{определяем площадь}EndЗадания для самопроверкиЗадание 1.
Реализуйте класс, диафамма которого изображена на рис. 9.6, а.Разработайте тестирующую программу.Задание 2. Спроектируйте класс для реализации объекта «Меню», который, получив сообщение «Изобразить меню», выводит на экран окно, включающее окнаменьшего размера, содержащие строки - названия пунктов (см. пример 8.4).
Разработайте тестирующую программу.11.3. НаполнениеНаполнением называют способ конструирования классов, при котором встроящийся класс включают неопределенное количество: от О до сравнительно больших значений (на практике обычно до нескольких десятков) объектов других классов.Пример 11.3. Разработать класс для реализации объекта Комната с балконом, который должен реагировать на запрособ общей площади (рис.
11.7).Площадь?КомнатаБалкон в комнате может существовать илис балкономнет. Для простоты будем считать, что в комнате может быть не более одного балкона прямоРис. 11.7. Объект Комната угольной формы. Следовательно, разрабатывас балкономемый класс можно наследовать от класса332//. Иерархии классовTRoom и включить в него указатель на объекткласса TRoom (рис. 11.8). Он должен добавлятьсвои методы определения площади и инициализации объектов, учитывающие наличие или отсутствие балкона.0..1TRoomlength, widthSquare(), Init ( )ITBRoompB:^TRoomBSquare(), InitAII ( )Program ex;Uses Room;TypeTBRoom =object(TRoom)Рис. 11.8. ДиаграммаpB: ^TRoom;классов для TBRoomfunction BSquare:real;procedure InitAll(lw:real; lb,wb:real);end;Procedure TBRoom.
InitAII;BeginInit(l,w);if (Ib^O) or (wb-=OJ thenpB—nilelsebeginNew(pB);pB''Jnit(lb,wb);end;End;Function TBRoom, BSquare;BeginifpB=nil then BSquare: = Square;else BSquare: = Square ^pB\ Square;End;Var B:TBRoom; {объявляем объект-переменную}BeginВ, InitAll(3J,5J,L8A8); (инициализируем объект}WriteLn('Площадь комнаты с балконом = \B.BSquare);EndПроцесс выделения памяти под динамические поля объекта необходимоконтролировать.
С этой целью используют средства контроля выделения памяти, рассмотренные в параграфе 7.2. Кроме этих средств существуют специальные средства контроля выделения памяти под динамические поля, которые обычно используют при разработке конструкторов.
Эти средства иприемы их использования будут рассмотрены в параграфе 11.7.333Часть 2. Объектно-ориентированное программированиеЗадания для самопроверкиЗадание 1. Реализуйте класс, диаграмма которого изображена на рис. 9.6, б.Разработайте тестирующую программу.Задание 2. Спроектируйте класс для реализации объекта «Настраиваемое меню», который, получив сообщение «Изобразить меню», выводит на экран окно,включающее окна меньшего размера, содержащие строки - названия пунктов (см.пример 8.4).
Объект должен создаваться в процессе работы программы. Количествопунктов меню и заголовки должны вводиться с клавиатуры. Разработайте тестирующую программу.11.4. Простой полиморфизмКак уже говорилось в параграфе 9.3, возможность переопределения методов при наследовании является частным случаем полиморфизма.Пример 11.4. Разработать класс для реализации объекта Трехмернаякомната 2, который должен реагировать на запрос о суммарной площади стени потолка (рис.
11.9).Класс, реализующий данный объект, будем наследовать от классаTRoom. Этот класс должен включать метод определения площади стен и потолка. Логично назвать этот метод Square, но метод с таким именем уже определен в базовом классе. Поскольку объект не должен реагировать на запрос о площади комнаты, метод Square базового класса можно переопределить (рис. 11.10).Помимо переопределения метода Square класс TVRoom2 переопределяет метод инициализации полей объекта Init, добавляя определение значениянового поля height.В Borland Pascal сохраняется возможность обращения к переопределенному родительскому методу из методов класса-потомка. С этой целью передименем метода указывают служебное слово inherited или имя класса-родителя и точку:inherited Squareили TRoom.
SquareОкончательно получаем следующую программу:Площадь?Трехмернаякомната 2Рис. 11.9. ОбъектТрехмерная комната 2334TRoomlength, widthSquare(), Init()TVRoom2heightSquare(), Init()Рис. 11.10. Иерархия классовдля класса TV Room//. Иерархии классовProgram ex;Uses Room;Type TVRoom2 = object(TRoom)height;real;{дополнительное поле класса}function Square:real; {переопределенный метод класса}procedure InU(l, w,h:real); {переопределенныйинициализирующий метод}end;Procedure TVRoom2,Init;Begin{инициализируем поля базового класса}inherited InitQyW); {или TRooniInit(l,w) }height:-h; {инициализируем собственное поле класса}End;Function TVRoom2.Square;BeginSquare: ^inherited Square-^2'^height*(length'^width); {обращаемсяк переопределенному методу базового класса}End;VarA:TVRoom2;BeginAJnit(3A5.l2.8);WriteLnCrinouiadb стен и потолка = \A.Square);EndПодключаемый метод в этом случае определяется типом объекта, для которого метод вызывают.