Полиморфизм и виртуальные методы



Полиморфизм — это возможность использовать одинаковые имена для методов, входящих в различные классы.

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

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

Type

// базовый класс

TPerson=class

  fname:string;{ имя }

   constructor Create(name:string);

   function info: string; virtual;

end;

// производный от базового TPerson

TStud=class(TPerson)

fgr:integer; { номер группы }

constructor Create(name:string;gr:integer);

function info: string; override;

end;

// производный от базового TPerson

TProf=class(TPerson)

fdep:string; { название кафедры }

constructor Create(name:string;dep:string);

function info: string; override;

end;

В каждом из этих классов определен метод info. В базовом классе с помощью директивы virtual метод info объявлен виртуальным. Объявление метода виртуальным дает возможность дочернему классу произвести замену виртуального метода своим собственным. В каждом дочернем классе определен свой метод info, который замещает соответствующий метод родительского класса. При этом метод порожденного класса, замещающий виртуальный метод родительского класса, помечается директивой override. Ниже приведено определение метода info для каждого класса.

 

function TPerson.info:string;

Begin

result:=’’;

end;

function TStud.info:string;

Begin

  result:=fname+' гp.'+IntTostr(fgr);

end;

 

function TProf.info:string;

Begin

   result:=fname+'каф.'+fdep;

end;

В программе список людей можно представить массивом объектов класса TPerson, например

1ist:array[1..SZL] of TPerson; // SZL — размер массива

Здесь следует отметить, что объект list— это массив указателей. Объявить подобным образом список можно потому, что Object Pascal позволяет указателю на родительский класс присвоить значение указателя на дочерний класс. Поэтому элементами массива list могут быть как объекты класса TStud, так и объекты класса TProf.

Вывод списка можно осуществить применением метода info к элементам массива, например, так:

st:=’’;

for i:=l to SZL do

if list[i] <> NIL

              then st:=st+info.list[i]+#13;

ShowMessage(st);

Во время работы программы каждый элемент массива может содержать как объект типа TStud, так и объект типа TProf. Концепция полиморфизма обеспечивает возможность применения к объекту именно того метода, который соответствует типу объекта.

Задание 1. Подготовить и выполнить программу, в которой формируется и выводится список студентов и преподавателей с использованием рассмотренных выше объявлений классов TPerson, TStud и TProf.

Решение задачи выполнить в следующей последовательности:

1. Открыть новый проект командой главного меню File|New Application и в качестве заголовка ввести текст “Студенты и преподаватели”.

2. Создать главную форму, поместив на нее со страницы Standard следующие компоненты:

q две компоненты типа Edit, разместив их в правой верхней части окна формы. Исходное содержимое компонент удалить. Первая компонента будет использоваться для ввода фамилии студента или преподавателя, а вторая – для ввода номера группы или названия кафедры;

q слева от каждой строки ввода поместить по компоненте типа Label. Первой метке задать значение “Фамилия”, а второй – “Группа или кафедра’;

q в левой нижней части формы поместить компоненту типа GroupBox без названия, задав ей размеры, соответствующие примерно 1/5 площади формы;

q внутри компоненты GroupBox поместить две компоненты типа RadioButton (переключатели) с названиями: первая – “студент”, вторая – “преподаватель”;

q справа от компоненты GroupBox поместить две кнопки с названиями “Добавить в список” и “Вывести список”.

3. В интерфейсной части модуля ввести следующие разделы:

q раздел описания типов (помимо основного, автоматически создаваемого средой), в котором разместить описания классов TPerson, TStud и TProf из п. 2.7;

q раздел констант, задав в нем максимальный размер списка-массива элементов типа TPerson (не более 10-12);

q в раздел var добавить описание массива объектов класса TPerson (см. п. 2.7) и описание переменной, определяющей текущее число людей в списке.

4. В исполнительную часть модуля поместить описания следующих методов:

q метода класса TPerson, обеспечивающего создание объекта этого класса и доступ к его свойствам (см. п. 2.4);

q методов классов TStud и TProf c использованием обращения к конструктору родительского класса TPerson (см. п. 2.5);

q метода info для классов TPerson, TStud и TProf (см. п. 2.7).

5. В эту же часть модуля поместить описания следующих обработчиков:

q обработчика, который запускается нажатием кнопки “Добавить в список”. Он должен в зависимости от состояния переключателей “студент”, “преподаватель” формировать массив элементов класса TStud или TProf. При этом фамилии должны вводиться в первой строке ввода, а номер группы или название кафедры – во второй. Ввод должен выполняться в соответствии с заданным максимальным размером списка;

q обработчика, который выполняется в результате нажатия на кнопку “Вывести список” Он должен применять метод info к каждому объекту списка и выводить список (см. п. 2.7).

6. Выполнить сохранение и компиляцию файла программы.

7. Проверить работу программы в двух случаях:

a) формирование и вывод списка студентов (на примере своей группы);

b) формирование и вывод списка преподавателей кафедры (например, ЭВМ).

 

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

DELPHI содержит сложную иерархию классов, которые можно использовать в программе, создавая объекты этих классов или формируя-классы потомки. В начале этой иерархии стоят классы, называемые абстрактными классами. Для них нельзя создать полноценные работающие объекты, но они являются родоначальниками целых семейств классов, для которых такие объекты уже могут быть созданы. Исходя из свойства наследования, в абстрактных классах помещены характеристики, присущие всем классам их семейств.

Структура некоторых абстрактных классов, находящихся в начале иерархии классов, приведена на рисунке.[10]

 

 

 

 


Класс TObject является предком всех других классов, используемых в DELPHI. Он включает в себя характеристики, свойственные всем используемым классам. Некоторые методы класса TObject могут использоваться без создания соответствующих объектов с учетом того, что реального объекта такого класса может и не быть. Эти методы позволяют получить общие характеристики класса – адрес таблицы, содержащей характеристики класса, имя класса, имя предка класса, характеристики методов и т. д. Примеры некоторых методов класса TObject:

q ClassName – функция класса (типа ShortString) формирует строку, содержащую имя класса, данное ему при создании;

q ClassParent – функция, определяющая класс непосредственного предка данного класса;

q ClassType – функция возвращает класс конкретного объекта;

q InstanceSize – функция (типа Longint) возвращает размер класса или объекта в байтах;

q FieldAddress(Name) – функция типа Pointer возвращает адрес поля объекта с именем Name типа ShortString.

Класс TPersistent (Постоянный) является потомком класса TObject и предком всех классов, объекты которых могут быть помещены в память и взяты из памяти. Основными потомками класса TPersistent являются классы TComponent (Компонента) – предок всех компонент проекта; TStrings (Строки) – предок всех списков строк; TCollection (Коллекция) – коллекция (список) элементов; TGraphicObject (Графический объект), TCanvas (Канва – основа для рисования), TGraphic (Графический элемент), TPicture (Изображение) – классы, образующие так называемый графический инструментарий DELPHI.

Класс TControl является родоначальником всех элементов управления, с помощью которых выводится информация на экран и с помощью которых можно вводить информацию в программу, используя клавиатуру и мышь. Его потомок класс TWinControl служит для создания окон Windows. Класс TGraphicControl отличается от класса TWinControl отсутствием у объектов его семейства оконной функции, в связи с чем такие элементы либо служат для вывода на экран информации, либо являются чисто декоративными[11].

Методы базового класса Tobject, как отмечалось выше, позволяют легко получать информацию о характеристиках созданного класса и его потомках.

 

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

Решение задачи выполнить в следующей последовательности:

1. Открыть новый проект и в качестве заголовка формы ввести текст “Задание 2”.

2. На форму поместить две кнопки: “Операция” и “Закрыть”.

3. В интерфейсной части модуля после описания класса TForm1 поместить описание нового класса с именем TNewForm:

TNewForm=class(TForm)

class procedure ClassMessage;

end;

В этом классе введен метод классаClassMessage (см. п.2.3), который будет формировать строку с требуемой информацией.

4. В исполнительной части модуля поместить описание этого метода:

class procedure TNewForm.ClassMessage;

var s: string;

Begin

s:=’Имя класса:’+ClassName+#13#10’Предок:’+ClassParent.ClassName;

Application.MessageBox(PChar(s),’Информация о классе’,MB_OK);

end;

В этом методе формируются две строки: первая отображает имя класса, для чего используется метод класса ClassName, определенный в классе TObject,  вторая отображает имя непосредственного предка.

Для вывода имени предка используются два метода класса – ClassParent и ClassName, определенные в классе TObject. Затем информация с помощью стандартного метода MessageBox объекта Application выводится в информационном окне на экран. Это окно имеет заголовок “Информация о классе” и одну кнопку управления “OK”.

5. В заготовку обработчика событий кнопки “Операция” поместить оператор обращения к методу класса ClassMessage:

TNewForm.ClassMessage;

Примечание. Метод класса ClassMessage используется в данном случае, несмотря на то, что ни одного объекта класса TNewForm не создано (см.п.2.3).

6. Подготовить стандартный обработчик событий для кнопки “Закрыть”.

7. Выполнить сохранение файлов проекта и модуля в текущем каталоге, провести компиляцию и запуск программы на выполнение.

Нажать кнопку “Операция”. На экран должно быть выведено окно с информацией о типе класса и его предка.

8. Завершить работу программы нажатием кнопки “Закрыть”.

 

В Object Pascal можно задавать указатель на класс, называемый метаклассом. Для этого в объявлении записываются ключевые слова class of, после чего указывается имя класса, ссылка на который формируется:

Type

<имя типа>=class of <базовый класс>;

Примером может быть следующее описание:

Type

TControlClass=class ofTControl;

Этот тип является стандартным в DELPHI и именно так он определяется в модуле Controls. Введя такой тип данных, далее можно задавать переменные этого типа, например:

var ControlClass: TControlClass;

Значениями такой переменной могут быть классы, входящие в семейство исходного класса TControl: сам класс TControl, класс TForm, класс TButton и т. д. Таким образом, метакласс может быть указателем на любой класс, входящий в семейство исходного класса.

Введение метаклассов удобно для создания универсальных подпрограмм, которые могут работать с объектами из целого семейства классов, причем заранее неизвестно, какой из этих объектов будет использоваться. В ряде случаев это существенно упрощает создаваемую программу.

 

Задание 3. Подготовить и выполнить программу, выводящую сообщение о характеристиках любого класса – название его типа и название типа его непосредственного предка.

Решение задачи выполнить в следующей последовательности:

1. Открыть новый проект и в качестве заголовка формы ввести текст “Задание 3”.

2. На форму поместить три кнопки: “Операция1”, “Операция2” и “Закрыть”. С помощью первых двух кнопок будет получаться информация о форме и помещенной на ней кнопке.

3. В интерфейсной части модуля после описания класса TForm1 поместить описание нового класса с именем TNew2Form:

TNew2Form=class(TForm)

class procedure ClassMessage(TypeClass:TCass);

end;

В этом классе введен метод классаClassMessage (см. п.2.3), который будет формировать строку с требуемой информацией.

4. В исполнительной части модуля поместить описание этого метода:

class procedure TNew2Form.ClassMessage(TypeClass:TCass);

var s: string;

Begin

s:=’Имя класса:’+ TypeClass.ClassName+#13#10’Предок:’+

TypeClass.ClassParent.ClassName;

Application.MessageBox(PChar(s),’Информация о классе’,MB_OK);

end;

В отличие от метода класса ClassMessage предыдущего задания в данном случае этому методу передается параметр-метакласс TypeClass, для которого и определяются имя класса и имя его непосредственного предка. При обращении к этому методу в качестве входного параметра можно использовать любой класс, и именно для него будет получена необходимая информация.

5. Для кнопки “Операция1” создать обработчик события, поместив в его тело следующий оператор:

TNew2Form.ClassMessage(Form1.ClassType);

Этот оператор вызывает метод класса ClassMessage, и ему передается тип формы Form1, который получается для объекта Form1 с помощью метода класса ClassType, определенного в классе TObject.

6. Для кнопки “Операция2” создать обработчик события, поместив в его тело следующий оператор:

TNew2Form.ClassMessage(Form1.Button1.ClassType);

Этот оператор передает методу класса ClassMessage тип кнопки, для которого и получается необходимая информация.

7. Подготовить стандартный обработчик событий для кнопки “Закрыть”.

8. Выполнить сохранение файлов проекта и модуля в текущем каталоге, провести компиляцию и запуск программы на выполнение.

9. Последовательно нажать кнопки “Операция1”, “Операция2”. При этом на экран должны быть выведены два окна с информацией о типе класса и его предка – либо формы, либо кнопки.

10. Завершить работу программы нажатием кнопки “Закрыть”.

Задание 4. Дополнить программу задания 1 описаниями класса TNew2Form и метода ClassMessage из программы задания 3. Поместить на форму программы задания 1 кнопки “Операция1” и “Операция2” и с помощью соответствующих обработчиков (по аналогии с обработчиком кнопки “Операция2” в задании 3) получить информацию о классах TStud и TProf.

Задание 5. Подготовить и выполнить программу построения графика функции Y=F(X), которая задается следующим образом:

0 <= X < 50      Y = 0,

50 <= X < 100   Y = X - 50,

100 <= X < 150  Y = 50,

150 <= X < 200  Y = -(X - 200),

200 <= X < 250    Y = 0.

Все размеры заданы в пикселах.

Решение задачи выполнить в следующей последовательности:

1. Открыть новый проект и в качестве заголовка формы ввести текст “Задание 4”.

2. На форму поместить кнопки: “Операция”, “Закрыть”, и компоненту Image (Изображение) для размещения на ней графика. Задать ширину компоненты в 300 пикселов, а высоту – в 150 пикселов. Выровнять компоненту относительно центральной вертикальной оси.

3. Для кнопки “Операция” подготовить текст программы обработчика, рисующего заданный график с использованием свойств и методов графических инструментов DELPHI, в частности объектов класса TCanvas Pen (перо), PenPos и методов LineTo и MoveTo[12].

4. Выполнить сохранение файлов проекта и модуля в текущем каталоге, провести компиляцию и запуск программы на выполнение.

5. Завершить работу программы нажатием кнопки “Закрыть”.

4. Отчет по лабораторной работе

Отчет должен быть оформлен в соответствии с требованиями, что в лабораторной работе № 1.

 

Литература


Дата добавления: 2018-04-15; просмотров: 600; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!