Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ООП / Заочники / ООП_ЛабРаб_Методичка

.pdf
Скачиваний:
30
Добавлен:
08.06.2015
Размер:
770.97 Кб
Скачать

Лабораторная работа № 3

Иерархия классов и элементов управления

Цель работы: знакомство с принципами построения иерархии классов и элементов управления в Delphi, освоение основных средств и приемов работы с иерахическими структурами в среде Delphi.

1. Задание

1.1.Добавить в форму из лабораторной работы №1 две закладки «Элементы управления», «Иерархия объектов».

1.2.На закладке «Элементы управления» показать иерархию расположения объектов формы. Иерархию отобразить в виде дерева с помощью компонента TTreeView. Для текущего узла дерева справа в StringGrid показывать его свойства (Name, Type, Top, Left, Width, Hight).

1.3.На закладке «Иерархия классов» отобразить иерархию классов, использованных для создания объектов формы. Иерархию отобразить в виде дерева с помощью компонента TTreeView. Для текущего узла дерева справа показывать размер его объектов в байтах.

2. Краткая теория

2.1. TTreeView - дерево иерархии

Компонент TTreeView служит для показа ветвящихся иерархических структур, таких как дерево наследования объектов или файловая структура диска. Он содержит связанные узлы, каждый из которых может содержать пиктограмму, текст и произвольный объект. Любой узел может иметь собственный список подузлов, которые можно раскрывать или закрывать щелчком мыши на пиктограмме узла.

Для наполнения списка на этапе конструирования программы нужно щелкнуть по компоненту правой кнопкой мыши и выбрать Items Editor, либо щелкнуть по нему дважды, либо, наконец, щелкнуть по кнопке в свойстве Items - во всех случаях на экране появится окно редактора компонента. Чтобы начать наполнение, щелкните по кнопке New Item и введите связанный с узлом текст в поле Text. С помощью Image Index панели Item Properties устанавливается индекс связанной с узлом пиктограммы, с помощью Selected Index - индекс пиктограммы для выбранного узла. Для ввода подузла любого уровня сначала нужно щелкнуть в окошке Items по узлу, который должен стать родительским, и лишь затем - на кнопке New Subltem.

Для ввода списка в режиме прогона программы широко используется центральное свойство компонента - Items типа TTreeNodes, открывающее индексированный доступ ко всем узлам списка. Каждый узел описывается классом TTreeNode, имеющим свои собственные методы и свойства. Его свойство Item содержит список (массив) всех подузлов данного узла. С помощью метода ТТrееView.Items.AddChildObject(Node: TtreeNode;S : string; Ptr:Pointer) в конец списка дочерних узлов узла Node можно добавить новый подузел. Параметр S устанавливает значение свойства Text (подпись узла в дереве). Параметр Ptr устанавливает значение свойства Data, которе указывает на связанные с узлом данные.

Для получения сведений об объекте, на который указывает свойство Data объекта класса TTreeNode, необходимо привести его к нужному типу данных. В дереве на

закладке «Элементы управления» свойство Data указывает на объекты формы, классы которых наследуются из класса TControl. Свойства, которые нобходимо отображать, обявлены в родительском классе. Поэтому достаточно преобразовать указатель к типу TControl. Например, для получения имени объекта, с которым связан узел Node, необходимо написать:

TControl(Node.Data).Name;

В дереве на закладке «Иерархия классов» свойство Data указывает на ссылку на класс. Свойства, которые нобходимо отображать, обявлены в типе TClass - родительском классе для всех ссылок на классы. Поэтому достаточно преобразовать указатель к типу

TClass, например: TClass(Node.Data).ClassName;

Метод TreeView.Items.GetFirstNode:TTreeNode возвращает указатель на самый первый узел в списке.

Метод TTreeView.Select(const Nodes: array of TTreeNode) выделяет в дереве перечисленные в массиве узлы, например:

TreeView2.Select([TreeView2.Items.GetFirstNode]);

2.2. TStringGrid - таблица строк

Компонент TStringGrid предназначен для создания таблиц, в ячейках которых располагаются произвольные текстовые строки.

Таблица делится на две части - фиксированную и рабочую. Фиксированная служит для показа заголовков столбцов/рядов и для ручного управления их размерами. Обычно фиксированная часть занимает крайний левый столбец и самый верхний ряд таблицы, однако с помощью свойств FixedCols и FixedRows можно задать другое количество фикси- рованных столбцов и рядов (если эти свойства имеют 0, таблица не содержит фиксированной зоны). Рабочая часть - эта остальная часть таблицы. Она может содержать произвольное количество столбцов и рядов, более того, эти величины могут изменяться программно. Рабочая часть может не умещаться целиком в пределах окна компонента, в этом случае в него автоматически помещаются нужные полосы прокрутки. При прокрутке рабочей области фиксированная область не исчезает, но меняется ее содержимое - заголовки строк и рядов.

Центральным свойством компонента является Cells - двумерный массив ячеек, каждая из которых может содержать произвольный текст. Конкретная ячейка определяется парой чисел - номером столбца и номером ряда, на пересечении которых она находится (нумерация начинается с нуля). Свойство Cells имеет тип string, поэтому программа может легко прочитать или записать содержимое нужной ячейки. Например:

StringGrid1.Cells[0,0] := 'Name';

Количество ячеек по каждому измерению хранит пара свойств ColCount (количество столбцов) и RowCount (количество рядов). Значения этих свойств и, следовательно, размеры таблицы могут меняться как на этапе разработки программы, так и в ходе ее работы, однако их значения должны быть как минимум на единицу больше соответственно значений в свойства FixedCols и FixedRows, определяющих размеры фик- сированной зоны. Свойство ColWidth[i] позволяет для i-й колонки установить индивидуальную ширину.

2.3. Операции с классами

Для классов определены операции отношения = и <>. Кроме того, для классов определены еще две операции: as (как) и is (является). Первым операндом в обеих операциях является объект, вторым класс.

Если А объект, а С класс, то выражение A as С возвращает тот же самый объект, но рассматриваемый как объект класса С. Операция даст результат, если

указанный класс С является классом объекта А или одним из наследников этого класса. В противном случае будет сгенерировано исключение.

Наиболее часто операция as применяется к параметру Sender, передаваемому во все обработчики событий как объект источник события и имеющему тип TObject, в котором очень мало свойств для идентификации объекта. Например:

if (Sender as TComponent) .Name = 'Button2' then ...;

Этот оператор выбирает событие, связанное с компонентом, имеющим имя «Button2», и не реагирует на события, связанные с другими компонентами.

Выражение A is С позволяет определить, относится ли объект А к классу С или к одному из его потомков. Если относится, то операция is возвращает true, в противном случае false. Например, оператор:

if Sender is TButton then ...;

будет реагировать только на объекты класса TButton или потомков этого класса.

2.4. Родительские и дочерние компоненты

Все элементы управления, которые используются для построения форм Windows, являются наследниками класса TControl. Часть из них является окнами (обладает дескрипторами окон) и способны получать и обрабатывать Windows-сообщения. Другие окон не имеют, но обязательно включаются в состав оконных компонентов, которые управляют ими, согласуясь с сообщениями Windows. Оконные элементы управления обла- дают специальной оконной функцией, в которую Windows посылает управляющие сообщения (например, извещения о манипуляции пользователя с мышью или о нажатии клавиш клавиатуры). В терминологии Windows такие элементы называются родительскими, а связанные с ними неоконные элементы - дочерними. Оконный компонент (наследник класса TWinControl) может выступать как родительский не только по отношению к неоконным компонентам, но и к оконным. В этом случае он просто транслирует управляющие сообщения Windows в оконные функции дочерних компонентов. Обязательным требованием Windows является визуальная синхронизация дочерних элементов: они не могут выходить из границ своего родителя и появляются и исчезают вместе с ним. Иными словами, родитель с дочерними элементами образует древовидную структуру и рассматривается Windows как единое целое.

Класс TControl определяет свойство Parent, которое содержит ссылку на родительский компонент, наследник класса TWinControl.

Класс TWinControl имеет следующие свойства:

ControlCount - счетчик дочерних элементов управления;

Controls – массив дочерних элементов управления (наследников классов

TWinControl и TControl);

Controls[i].Name – идентификатор дочернего элемента.

Построение дерева необходимо начинать с его корня, которым является сама форма. Наиболее простым способом построеия дерева является использованием рекурсии.

procedure TForm1.AddSubNodes(Node : TTreeNode;Cntrl: TControl); var

i : integer;

NewNode : TTreeNode; s : string;

MyClass: TClass;

begin

//Создание узла, соответствующего элементу управления Cntrl if Cntrl.Name='' then s:='<без имени>'

else s:=Cntrl.Name; NewNode:=TreeView1.Items.AddChildObject(Node,s,Cntrl);

//Добавить в дерево иерархии классов узел для класса объекта Cntrl MyClass:= Cntrl.ClassType; // Получение ссылки на класс

AddClass(MyClass); // Добавление класса в дерево иерархии классов

//Если элемент управления типа TWinControl, то он может содержать другие элементы

//управления, которые необходимо включить в дерево

if Cntrl is TWinControl then with (Cntrl as TWinControl) do

//Построение фрагмента дерева элементов управления, непосредственно подчиненных

//элементу управления Cntrl

for i:=0 to ControlCount-1 do begin //ControlCount - счетчик элементов управления AddSubNodes(NewNode,Controls[i] as TControl);

end;

end;

2.5. Ссылки на классы

Каждый класс содержит поле ClassType, являющееся ссылкой на класс.

Cсылки на классы это объекты, сохраняющие информацию о каждом классе в целом вместо хранения информации для определенного экземпляра класса. Ссылка на класс TObject в Delphi имеет специальный тип данных, объявленный как:

type

TClass = class of TObject;

Ссылки на класс используют правила совместимости типа, связанные с наследованием, точно так же, как другие объекты. Delphi определяет несколько таких ссылок на классы,

как TClass (являющийся классом TObject), TComponentClass, TControlClass и многие другие.

Для любой ссылки на класс TClass можно применять любой из методов класса TObject, перечисленных ниже:

ClassName: возвращает строку с именем класса;

ClassNameIs: проверяет имя класса;

ClassParent: возвращает ссылку на родительский класс;

ClassInfo: возвращает указатель на информацию о типе класса во время выполнения программы (Run-Time Type Information — RTTI);

InheritsFrom: проверяет, наследуется ли класс (прямо или косвенно) из данного базового класса;

InstanceSize: возвращает размер объектов.

2.6.Иерархия классов

Для построения дерева, отображающего иерархию классов, используется метод ClassParent ссылки на класс TClass. Для поиска родительского узла метод AddClass вызывается рекурсивно, что гарантирует добавление всех родительских классов в обратном порядке до класса TObject, который не имеет родительского класса. Метод AddClass создает узел, соответствующий классу, если узел класса не найден в TreeView, и возвращает сылку на узел нового класса.

function TForm1.GetNode(ClassName: string): TTreeNode; var

Node1 : TTreeNode; begin

//Поиск узла, соответсвующего классу

Result:= nil; // не найден

//поиск узла в дереве

Node1:= TreeView2.Items.GetFirstNode; while Node1 <> nil do begin

if Node1.Text = ClassName then begin Result := Node1;

Exit;

end;

Node1:= Node1.GetNext; end;

end;

function TForm1.AddClass(NewClass: TClass): TTreeNode; var

ParentNode: TTreeNode; begin

// поиск узла класса в дереве

Result := GetNode(NewClass.ClassName);

if Result = nil then begin // если класс не найден if NewClass.ClassParent<>nil then begin

// поиск родителя и добавление, если узел родительского класа не найден

ParentNode := AddClass(NewClass.ClassParent) ; // добавление нового класса

Result := TreeView2.Items.AddChildObject(ParentNode,NewClass.ClassName,Pointer(NewClass));

end else

// добавление нового класса как корневого узла

Result := TreeView2.Items.AddChildObject(nil,NewClass.ClassName,Pointer(NewClass)); end;

end;

3.Методика выполнения

3.1.Начните в Delphi новый проект и сохраните его в отдельном каталоге.

3.2.Удалите из проекта модуль Unit1 (Form1) (меню Project>Remove from Project…).

3.3.Скопируйте в рабочий каталог проекта файлы с расширением *.pas и *.dfm из проекта, разработанного в лабораторной работе №1.

3.4.Добавьте в проект скопированные файлы (меню Project>Add to Project…).

3.5.Добавьте в форму новые закладки и объекты. Узлы деревьев на этапе конструирования создавать не нужно. Деревья создаются программно.

3.6.Добавьте в форму методы для построения дерева иерархии классов и дерева иерархии элементов управления формы.

3.7.В обработчике события OnCreate формы задайте ширину и заголовки колонок объекта StringGrid и вызовите метод для построения дерева иерархии элементов управления формы AddSubNodes(nil,Form1).

3.8.Используйте обработчик события OnChange дерева TreeView1 (и TreeView2) для вывода сведений о выбранном узле дерева справа от него. Параметр Node указывает на выбранный в дереве узел. Sender представляет объект, обработчик события которого вызван, т.е. TreeView1 или TreeView2.

3.9.Проверьте работу программы. Исследуйте иерархию элементов управления и иерархию классов. Ответьте на контрольные вопросы.

4.Содержание отчета

Отчет готовится один на бригаду в рукописном или печатном виде и должен содержать следующие разделы:

-задание;

-листинг программы с подробными комментариями;

-4 копии экранных форм, на которых должны быть представлены 4 закладки с указанием идентификаторов всех объектов формы. В дереве иерархии классов и дереве иерархии элементов управления все узлы должны быть раскрыты.

5.Контрольные вопросы

5.1.Объясните устройство компонента TTreeView и основные приемы работы с ним.

5.2.Объясните устройство компонента TStringGrid и основные методы для работы с ним.

5.3.Объясните алгоритм построения дерева иерархии классов.

5.4.Объясните алгоритм построения дерева иерархии элементов управления формы.

5.5.Чем отличается дерево иерархии классов от дерева иерархии элементов управления формы?

5.5.В чем разница между операциями as и is?

5.6.Как изменяется значение Size при выборе узлов дерева иерархии? Чем это объясняется?

5.7.Как изменятся параметры элемента управления Form1 при перемещении формы на экране и изменении размеров формы? Чем это объясняется?

Лабораторная работа № 4

Разработка и использование класса, содержащего методы, свойства, констуктор, деструктор

Цель работы: знакомство с принципами создания и использования классов в языке Object Pascal.

1.Задание

1.1.В соответствии с вариантом задания разработать класс для представления объектов предметной области.

1.2.Пользуясь средствами Borland Delphi, разработать Windows-приложение c графическим интерфейсом пользователя (окно Windows) для выполнения следующих операций с объектами:

ввод данных об объектах предметной области;

хранение данных в оперативной памяти в динамическом массиве;

просмотр данных об объектах в виде списка с указанием типа и наименования в соответствии с вариантом задания (компонент отображения). Для компонента TTreeView узлы, соответствующие типам объектов, создать с помощью окна

«TreeView Items Editor».

редактирование выбранного объекта;

удаление выбранного объекта;

1.3. Доступ к атрибутам объектов осуществлять только с помощью свойств класса.

 

 

 

Таблица 1. Варианты задания

Компонент

Предметная область

Список типов объектов

Атрибуты

бр.

отображения

 

 

 

1

TListBox

Графические

Трапеция, треугольник,

Тип, название, длина контура,

 

 

фигуры

прямоугольник, окружность

площадь

2

TTreeView

Микросхемы

Регистры, счетчики,

Тип, название, технология,

 

 

 

дешифраторы,

серия

 

 

 

мультиплексоры

 

3

TListView

Канцелярские

Карандаши, скоросшиватели,

Тип, название, артикул,

 

 

товары

тетради, фотоальбомы

производитель, цена

4

TListBox

Радиоэлектронные

Конденсаторы, резисторы,

Тип, название, цена,

 

 

элементы

транзисторы, диоды

количество в наличии

5

TTreeView

Комплектующие

Процессор, память, НЖМД,

Тип, модель, цена, количество

 

 

для ПК

монитор

в наличии

6

TListView

Графические

Линия, треугольник,

Тип, координаты центра,

 

 

фигуры

прямоугольник, окружность

количество вершин

7

TListBox

Микросхемы

Регистры, счетчики,

Тип, серия, цена, количество в

 

 

 

дешифраторы,

наличии

 

 

 

мультиплексоры

 

8

TTreeView

Канцелярские

Карандаши, скоросшиватели,

Тип, артикул, количество

 

 

товары

тетради, фотоальбомы

 

9

TListView

Радиоэлектронные

Конденсаторы, резисторы,

Тип, производитель, цена,

 

 

элементы

транзисторы, диоды

количество в наличии

10

TListView

Комплектующие

Процессор, память, НЖМД,

Тип, производитель, цена,

 

 

для ПК

монитор

количество в наличии

2. Краткая теория

Классы и объекты

Классами в Object Pascal называются специальные типы, которые содержат поля, методы и свойства. Как и любой другой тип, класс служит лишь образцом для создания конкретных экземпляров реализации, которые называются объектами. Важным отличием классов от других типов является то, что объекты класса всегда распределяются в куче, поэтому объект-переменная фактически представляет собой лишь указатель на динамическую область памяти. Однако в отличие от других указателей при ссылке на содержимое объекта запрещается использовать символ «^» за именем объекта.

Любой класс может быть порожден от другого класса. Для этого при его объявлении указывается имя класса-родителя:

TChildClass = class(TParentClass)

Порожденный класс автоматически наследует поля, методы и свойства своего родителя и может добавлять их новыми. Таким образом, принцип наследования

обеспечивает поэтапное создание сложных классов и разработку собственных библиотек классов.

Все классы Object Pascal порождены от единственного родителя - класса TObject. Этот класс не имеет полей и свойств, но включает в себя методы самого общего назначения, обеспечивающие весь жизненный цикл любых объектов - от их создания до уничтожения. Программист не может создать класс, который не был бы дочерним классом TObject. Следующие два объявления идентичны:

TaClass = class (TObject)

TaClass = class

Поля

Полями называются инкапсулированные в классе данные. Поля могут быть любого типа, в том числе - классами, например:

type

TMyClass = class alntField: Integer; aStrField: String; aObjField: TObject;

end;

Каждый объект получает уникальный набор полей, но общий для всех объектов данного класса набор методов и свойств. Фундаментальный принцип инкапсуляции требует обращаться к полям только с помощью методов и свойств класса. Однако в Object Pascal разрешается обращаться к полям и напрямую:

var

aObject: TMyClass; begin

aObject.alntField := 0; aObject.aStrField := 'Строка символов';

end;

Класс-потомок получает все поля всех своих предков и может дополнять их своими, но он не может переопределять их или удалять. Таким образом, чем ниже в