- •Объектно-ориентированный анализ
- •Объектно-ориентированное программирование.
- •Объектно-ориентированное проектирование.
- •Основные понятия объектно-ориентированного проектирования.
- •Классы и объекты в Object Pascal.
- •Важнейшие принципы объектно-ориентированного программирования.
- •Составляющие класса.
- •Объекты
- •Создание и уничтожение объектов.
- •Наследование конструкторов и деструкторов.
- •Свойства и инкапсуляция.
- •Статические методы.
- •Полиморфизм. Виртуальные и динамические методы.
- •Абстрактные методы.
- •Перекрытие виртуальных и динамических методов.
- •Как устроен объект изнутри
- •Перезагрузка методов.
- •Задача с использованием полиморфизма
- •Области видимости.
- •Создание класса комплексных чисел.
- •Создание класса векторов
- •Объект-список
- •Модуль по работе со списками
- •Основная программа по работе с объектами-списками
- •Система программирования Delphi
- •Терминология Delphi.
- •Первые шаги визуального программирования в среде Delphi.
- •Иерархия компонентов.
- •Собственники компонентов
- •Элементы управления.
- •Компоненты (tComponent)
- •Оконные не оконные
- •Родительские и дочерние компоненты.
- •Объектно-событийное программирование. События
- •Реакции на события
- •Программирование реакции на событие
- •Особенности реализации событий
- •Делегирование событий
- •Виды событий
- •Диалоги. Работа с файлами. Открытие и закрытие файлов с использованием стандартных диалоговых окон.
- •TOpenDialog и tSaveDialog – диалоги открытия и сохранения файлов (страница dialogs )
- •Компонент класса tform
- •Создание и использование форм
- •Шаблоны форм
- •Программы со многими формами
- •Модульный принцип построения программ.
- •Программные файлы. Основные типы файлов проекта. Простейшее приложение.
- •Структура головного файла проекта.
Перезагрузка методов.
Четвертая группа методов – перезагружаемые (Overload). Заметим, что и виртуальные и динамические методы могут быть перезагружаемыми. Перезагрузка нужна, чтобы произвести одинаковые или похожие действия с разнотипными данными. Статический метод перекрытия приводит к тому, что потомок «не видит» перекрытый родительский метод и может обращаться к нему только с помощью слова inherited, поэтому в Delphi используется перезагрузка, с помощью которой становятся видны одноименные методы как родителя, так и потомка.
Пример:
Type TFirst=class
i:Extended;
procedure SetData(x:Extended);
end;
TSecond=class(TFirst)
j:Integer;
procedure SetData(AValue:Integer);
end;
. . . . .
var T2:TSecond;
. . . . .
begin
T2.SetData (1.1); (1)
T2.SetData (1); (2)
В этом примере первый вызов метода SetData из объекта T2 с переменной =1.1 (не целая) вызовет ошибку! А второй вызов не приводит к ошибке, т.к. внутри объекта T2 статический метод с параметром типа Extended перекрыт одноименным методом с параметром типа Integer. Компилятор внутри T2 не признает параметр типа Extended.
Для доступа к методу SetData класса TFirst необходимо использовать служебное слово inherited. Например:
procedure TSecond.SetData;
begin
x :=1.1;
inherited SetData (x);
j:=x;
end;
Но нам нужно произвести схожие действия (1), (2) с разнотипными данными в строках одной программы.
Может быть, метод сделать виртуальным?
Нет, нельзя! Поскольку тип и количество параметров в одном и том же виртуальном методе должны в точности совпадать.
Начиная с версии Delphi4 появилась возможность перезагрузить методы (overload), это позволяет видеть одноименные методы как родителя, так и потомка. Чтобы одноименные методы можно было отличить друг от друга, каждый из них должен иметь уникальный набор параметров. В ходе компиляции при обращении к одному из одноименных методов компилятор проверяет тип и количество параметров обращения и на основе этой проверки выбирает нужный метод.
Overload – директива, позволяющая перезагрузить методы:
Type TFirst=class
i:Extended;
procedure SetData(x:Extended); Overload;
end;
TSecond=class(TFirst)
j:Integer;
procedure SetData(AValue:Integer); Overload;
end;
. . . . .
var T2:TSecond;
. . . . .
Теперь в программе можно использовать метод как родителя, так и потомка.
begin
T2.SetData (1.1);
T2.SetData (1);
Можно перезагрузить и виртуальный, и динамический методы. В этом случае надо добавить директиву reintroduce перед директивой overload.
Задача с использованием полиморфизма
Полиморфизм – это возможность использовать одинаковые имена для методов, входящих в различные классы. Концепция полиморфизма обеспечивает в случае применения метода к объекту использование именно того метода, который соответствует классу объекта.
Пусть определены 3 класса, один из которых является базовым для двух других:
Type
Tperson=class {базовый класс}
fname:string;
constructor Create(name:string);
function info:string; virtual;
end;
Tstud=class(Tperson) {класс– потомок}
fgr:integer; {поле для номера группы}
constructor Create(name:string;gr:integer);
function info:string; override;
end;
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+' gruppa '+inttostr(fgr);
end;
function Tprof.info:string;
begin
result:=fname+' department '+fdep;
end;
Далее в программе список всех людей можно представить массивом объектов класса Tperson. Отметим, что объект – указатель.
Список людей имеет вид:
list: array[1..szl] of Tperson; { szl –размер списка}
Объявить подобным образом список можно потому, что OP позволяет присвоить указателю на родительский класс значение указателя на класс– потомок. Поэтому элементами массива list могут быть как объекты класса Tstud, так и объекты класса Tprof.
Вывод списка можно осуществить применением метода info к элементам массива, например:
St:= ’’;
for i:=1 to szl do
if list[i]<>nil then
St:=St+list[i].info+#13;
ShowMessage('Spisok:'+#13+St); { вывод в окно сообщения}
Во время работы программы каждый элемент массива может содержать как объект типа Tstud, так и объект типа Tprof.
Концепция полиморфизма обеспечивает применение к объекту именно того метода info, который соответствует типу объекта.
Напишем программу, которая использует объявления классов Tperson, Tstud, Tprof, формирует список студентов и преподавателей и выводит полученный список в окно сообщения. Будем использовать визуальное программирование.
Окно формы будет иметь вид:
GroupBox1—это компонент , объединяющий группу компонентов, связанных по смыслу. В данном случае он включает 2 зависимых переключателя – RadioButton1 и RadioButton2
Текст модуля кода программы:
unit Polimorfizm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
Type
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Edit1: TEdit;
Edit2: TEdit;
GroupBox1: TGroupBox;
RadioButton1: TRadioButton;
RadioButton2: TRadioButton;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type Tperson=class
fname:string;
constructor Create(name:string);
function info:string; virtual;
end;
Tstud=class(Tperson) {класс– потомок}
fgr:integer; {поле для номера группы}
constructor Create(name:string;gr:integer);
function info:string; override;
end;
Tprof=class(Tperson) {класс– потомок}
fdep:string; ; {поле для названия кафедры}
constructor Create(name:string; dep:string);
function info:string; override;
end;
Сonst szl=10;
Var
Form1: TForm1;
list:array[1..szl] of Tperson;
n:integer;
implementation {исполняемая часть}
{$R *.DFM}
constructor Tperson.Сreate(name:string); {описание конструктора}
begin
fname:=name;
end;
constructor Tstud.Create(name:string;gr:integer);
begin
inherited create(name);
fgr:=gr;
end;
constructor Tprof.Create(name:string;dep:string);
begin
inherited create(name);
fdep:=dep;
end;
function Tperson.info:string;
begin
result:=fname;
end;
function Tstud.info:string;
begin
result:=fname+' gruppa '+inttostr(fgr);
end;
function Tprof.info:string;
begin
result:=fname+' department '+fdep;
end;
procedure TForm1.Button1Click(Sender: TObject);
//процедура обработки нажатия на кнопку «Добавить»
begin
if n<szl
then
begin
if RadioButton1.Checked
then
list[n]:=Tstud.Create(Edit1.text, StrtoInt(Edit2.text))
else
list[n]:=Tprof.Create(Edit1.text, Edit2.text);
n:=n+1;
end
else
ShowMessage('Spisok zapolnen');
end;
procedure TForm1.Button2Click(Sender: TObject);
//процедура обработки нажатия на кнопку «Список»
Var i:integer;
St:string;
Begin
for i:=1 to szl do
if list[i]<>nil then
St:=St+list[i].info+#13;
// list[i].info вызовет тот метод info, которому соответствует элемент
ShowMessage('Spisok:'+#13+St);
end;
end.
Процедура TForm1.Button1Click, которая запускается нажатием кнопки «Добавить» создает объект list[n] класса либо Tstud, либо Tprof.
Класс создаваемого объекта определяется состоянием переключателя RadioButton. Установка переключателя в положение Студент определяет класс Tstud, а в положение – Преподаватель определяет класс Tprof. Процедура TForm1.Button2Click, которая запускается нажатием кнопки Список (Button2) применяет метод info к каждому элементу массива list[i] как к объекту списка и формирует строку, представляющую весь итоговый список.
Виртуальность метода info обеспечивает применение к объекту именно того метода info, который соответствует типу объекта.
Отметим, что в данной программе результаты выводятся в окно сообщения процедурой ShowMessage. Например:
Showmessage('Spisok:'+#13+st);
Showmessage('spisok zapolnen');