38
04/23/22 1 Тема 14. Объекты и классы Понятие объекта и класса Свойства и методы класса Свойство наследственности Создание, уничтожение и операция присваивания объектов Понятие полиморфизма Статический, виртуальный и динамический способы реализации полиморфизма Примеры использования объектов

Лекция16_17_Объекты и классы

Embed Size (px)

DESCRIPTION

12/06/10 1  Основным понятием ООП является объект, который в Delphi представляет собой переменную нового структурированного типа, описываемого с помощью ключевого слова Class. (Объекты всегда распределяются в куче, переменная типа класс это указатель) 2

Citation preview

Page 1: Лекция16_17_Объекты и классы

04/23/23 1

Тема 14. Объекты и классы

Понятие объекта и класса Свойства и методы класса Свойство наследственности Создание, уничтожение и операция

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

способы реализации полиморфизма Примеры использования объектов

Page 2: Лекция16_17_Объекты и классы

04/23/23 2

Понятие объекта и класса С появлением языков SmallTalk и C++ в начале 80-х годов

возникла новая методология в технологии программирования – объектно-ориентированное программирование (ООП), основанное на более высоком уровне абстрагирования и модульности. Объекты придумали для упрощения разработки сложных программ и улучшения их качества. В языке Паскаль эта методология появилась, начиная с версии 5.5 (1985 г.).

Основным понятием ООП является объект, который в Delphi представляет собой переменную нового структурированного типа, описываемого с помощью ключевого слова Class. (Объекты всегда распределяются в куче, переменная типа класс это указатель)

Переменная типа Class под одним именем объединяет данные различных типов (поля) и процедуры их обработки (методы)

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

Page 3: Лекция16_17_Объекты и классы

04/23/23 3

Свойства: - этоМетоды чтения и записи некоторых

полей данных:a, b,…Методы (что умеет)Procedure Fp()Function Ff()

ИмяОбъект Delphi

Обработчики событий:(TForm1.Button1Click)Методы, вызываемые как реакция на событие

Структура объекта

Объектно-ориентированная программа – это совокупность объектов и способов их взаимодействия. Обмен между ними происходит посредством сообщений

поля данных: a, b, x, y, u, v,…

Page 4: Лекция16_17_Объекты и классы

04/23/23 4

• Unit uTob; Описание класса в разделе type • Interface• Type• Tobr=Class(Tobject)• a,b:Typr;• Property ca:Typr read a; //свойство• Function F1(форм.п.F1):T1; // заголовки методов

...• End;// Tobr• Tobp=Class(Tobr)• c,d,e:Typp;• Procedure P1(форм.п.Р1); // методы Tobp• end;// Tobp• Implementation• Function Tobr.F1;• Begin //описание методов• ...... • end;• Procedure Tobp.P1;• begin • ...... • end;• end.// конец uTob Все поля должны иметь разные имена

Page 5: Лекция16_17_Объекты и классы

04/23/23 5

Реализация наследственности Любой класс может быть порожден от другого класса.

Класс Tobp порожден от класса Tobr. Tobr – «класс родитель», а Tobp – «класс-потомок». Порожденный класс (Tobp) автоматически наследует поля и

методы своего родителя (в приведенном примере a, b, F1) и обогащает их новыми (c, d, e, P1).

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

Прародителем всех классов в Delphi является класс TObject.

Все компоненты Delphi представляют собой созданные разработчиками классы.

Page 6: Лекция16_17_Объекты и классы

04/23/23 6

Создание, уничтожение объектов• Как всякая динамическая переменная, объект перед началом

работы с ним должен быть создан конструктором класса TObject Create:

• <Имя-переменной-типа-класс> := <тип-класса> . Create;

• После окончания работы с объектом, выделенную под него память необходимо освободить деструктором класса TObject Destroy или Free:

• <Имя-переменной-типа-класс> . Free;

• в состав любого пользовательского класса могут быть введены свои методы Сonstructor и Destructor с дополнительными к Create и Free функциями.

• • Обычно это задание начальных условий совместно c Create или

закрытие файлов перед уничтожением Free.

Page 7: Лекция16_17_Объекты и классы

04/23/23 7

• Unit Unit1; //вызывающая программа• Interface• Implementation• uses uTob; //подключение модуля• Var Obp1,Obp2:Tobp; • Obr1:Tobr // объекты • Begin• ... • Obp1:=Tobp.Create; //создание объекта• Obp1.ca:=10; //полям присвоить значения• Obp1.P1(); //обращение к методу P1• Obp1.Free; //уничтожение объекта• ... • end.//Unit1

Page 8: Лекция16_17_Объекты и классы

04/23/23 8

Понятие свойства класса• Правила хорошего тона при ООП требуют: обращение к полям должно

осуществляться посредством методов.• • Но каждый раз писать имя метода при обращении к полю не всегда

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

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

• Свойства объявляются с помощью ключевых слов property… read…write…;

• var p:Tip;• property сp:Tip read методr write методw.

• Свойство связано с некоторым полем и указывает:• методr – метод чтения содержимого поля (функция без параметров)• (например, может сопровождаться выводом на печать)• методw - метод записи в это поле (процедура с одним параметром• имеющим тип свойства).

Page 9: Лекция16_17_Объекты и классы

04/23/23 9

• Пример описания свойства• Type• MyСlass=class( )• pole:byte;• //получить значение p• Function Getpole:byte;• Begin • Getpole:=p; //отразить p на форме• label1.caption:=inttostr(pole);• end;• // присвоить полю значение• Procedure Setpole(p0:byte);• Begin • p:=p0• end; //cp – имя свойства• Property cp:byte read getpole write Setpole;

(Property cp:byte read p;)(Property cp:byte write Setpole;)• ...• end;// MyСlass=class

Page 10: Лекция16_17_Объекты и классы

04/23/23 10

Работа со свойствомVar• Myobj:Myclass;xt:integer;• begin• ....• Myobj:= Myclass.Create;• ...• Myobj.cp:=10;• Myobj.Setpole(10);//это эквивалентно• Myobj.p:=10; // так можно но не рекомендуется • ....• xt:=Myobj.cp;• xt:=Myobj.Getpole;//это эквивалентно• xt:=Myobj.p; //так можно но не рекомендуется• ...• end;

Page 11: Лекция16_17_Объекты и классы

04/23/23 11

Свойства

• Фактически, свойства «живут» только до компиляции программы, во время которой заменяются методами или полями.

• В отличие от полей свойства не занимают места в памяти.

Page 12: Лекция16_17_Объекты и классы

04/23/23 12

операция присваивания Операция присваивания, например, obp2:=obp1;

приводит к копированию только указателя! Переменной родительского типа можно присвоить

значение переменной типа потомка, например, obr1:=obp1.

Обратное же присваивание запрещено. Однако, если переменная родительского типа

указывает на объект, фактически соответствующий переменной типа потомка, то при необходимости ее можно преобразовать к типу потомка с помощью оператора приведения объектных типов as :

obp2:= obr1 as Tobp;

Page 13: Лекция16_17_Объекты и классы

04/23/23 13

Понятие полиморфизма Свойство полиморфизма позволяет использовать одинаковое

название метода для решения сходных но несколько отличающихся у разных родственных классов задач.

Например, метод Add (добавить) имеется у многих компонент

Delphi, хотя в каждой компоненте реализуется по разному.

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

Obp1.Add; Obr1.Add; действуют по разному

Это и называется полиморфизмом объектов.

Page 14: Лекция16_17_Объекты и классы

04/23/23 14

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

стандартных программ для решения однотипных уравнений (в общем случае задач), которые можно расположить в порядке увеличения сложности и преемственности.

1)ах+b=0; 2)ах2+bx+c=0; 3)и т.п.

Начнем проектирование пакета программ с составления класса-прародителя

Page 15: Лекция16_17_Объекты и классы

04/23/23 15

• Type 1)ах+b=0• Tur1=Class(Tobject)• a,x:array of integer;• n:word;• Lw:TextFile;• procedure Init(no:word;ao,bo:extended);• procedure Solution;• procedure Resultw(FileN:string);• end;• procedure Tur1.Init;• begin n:=no;• SetLength(x,n);setLength(a,n+1)• a[0]:=ao; a[1]:=bo; • end;• procedure Tur1.Solution;• begin• x[0]:=-a[1]/a[0]• end;• procedure Tur1.Resultw;• begin• Assign(Lw,FileN); Rewrite(Lw);• for i:=0 to n do Writel(Lw,a[i]);• for i:=0 to n-1 do Writel(Lw,x[i]);• Close(Lw);• end;

Page 16: Лекция16_17_Объекты и классы

04/23/23 16

Решение 1)ах+b=0• Var Our1:Tur1;• . . .• Begin• Our1:=Tur1.Create;• Our1.Init(1,8,4);• Our1.Solution;• Our1.Resultw(’MySol’);• Our1.Free;• end;

• Результат: a0=8 a1=4 x0=0.5

Page 17: Лекция16_17_Объекты и классы

04/23/23 17

• Класс потомок для ах2+bx+c=0;• Здесь уже достаточно переписать 2 метода• Метод вывода результата будем брать родительский

• Type• Tur2=Class(Tur1)• procedure Init(no:word;ao,bo,co:extended);• procedure Solution;• end;

••

Page 18: Лекция16_17_Объекты и классы

04/23/23 18

• Реализация методов родителя•• procedure Tur2.Init; • begin• Inherited Init(no,ao,bo);• a[2]:=co;• end;• procedure Tur2.Solution;• Var d:extended;• begin• d:=sgrt(sqr(a[1])-4*a[0]*a[2]);• x[0]:=(-a[1]+d)/(2*a[0]);• x[1]:=(-a[1]-d)/(2*a[0]);• end;

Page 19: Лекция16_17_Объекты и классы

04/23/23 19

Решение ах2+bx+c=0• Var Our2:Tur2;• .......• Our2:=Tur2.Create;• Our2.Init(2,1.2,5,6.2);• Our2.Solution;• Our2.Resultw(’My Sol’);• Our2.Free;

• Поля данных не перекрываются. Их можно только дополнять в потомках, но не переопределять

Page 20: Лекция16_17_Объекты и классы

04/23/23 20

Если немного модифицировать родительский метод Init

• procedure Init(no:word;• const ao:array of extended);• procedure Tur1.Init;• begin n:=no;• SetLength(x,n);setLength(a,n+1)• for i:=0 to n do a[i]:=ao[i]; • end;

• То надобность перекрытия его в потомке отпадет:• Type• Tur2=Class(Tur1)• procedure Solution;• end;

Page 21: Лекция16_17_Объекты и классы

04/23/23 21

Взаимодействие объекта с методами

При объявлении в разделе var и создании create• Var ur1,up1:Tur1; ur2:Tur2;• ur1:=Tur1.Create;• up1:=Tur1.Create;• ur2:=Tur2.Create; каждый объект располагается по некоторому адресу. Причем все поля данных копируются, методы хранятся в одном экземпляре.

• Может возникнуть вопрос, как при обращении к методу ur1.Solution; ur2.Solution;

• удается определить, с какими полями работать, что делать?• Каждый раз, когда вызывается метод, ему через параметр-

указатель с именем Self, передается адрес того экземпляра объекта, который обращается к методу.

Page 22: Лекция16_17_Объекты и классы

04/23/23 22

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

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

Статические методы: характеризуются тем, что связывание метода с полями объекта осуществляется во время компиляции (раннее связывание). Предыдущие листинги иллюстрируют статические методы.

Виртуальные и динамические методы: связываются с объектом во время выполнения программы (позднее связывание).

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

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

Page 23: Лекция16_17_Объекты и классы

04/23/23 23

Реализации позднего связывания • Замещаемый одноименный метод родителя

объявляется как динамический или виртуальный с помощью ключевых словProcedure Ris;dynamic; (или virtual)

• В потомке замещающий метод объявляется директивой

Procedure Ris; override;

• Вызов перекрытого метода родительского класса в одноименном методе потомка достигается с помощью зарезервированного слова

Inherited Ris;(унаследованный).

Page 24: Лекция16_17_Объекты и классы

04/23/23 24

• Interface• Type• Tobr=Class(Tobject)• . . . • Procedure Ris; virtual• End;// Tobr

• Tobp=Class(Tobr)• . . .• Procedure Ris; override; • end;// Tobp• Implementation• . . . • Function Tobp.ris;• Begin• Inherited Ris; //рисуем то что может родитель• ......дорисовываем чего не хватает • end;

Пример организации перекрытия

Page 25: Лекция16_17_Объекты и классы

04/23/23 25

Реализация позднего связывания• Встретив объявления dynamic или virtual, компилятор

создает таблицы соответствия DMT и VMT.• • В этих таблицах помещаются адреса точек входа

методов.

• Таблица VMT “своего” класса хранится в каждом экземпляре объекта в особом, скрытом от программиста поле.

• • Таблица DMT хранится в VMT.• • При каждом обращении к методу компилятор

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

Page 26: Лекция16_17_Объекты и классы

04/23/23 26

Таблицы VMT DMT Отличие таблиц DMT и VMT в том, что o DMT содержит адреса только тех методов, которые объявлены

как dynamic в данном классеo VMT содержит адреса всех виртуальных методов данного

класса: как нововведенных, так и унаследованных от родителей.

Любой класс имеет VMT, т.к. в Delphi все классы являются потомками класса Tobject, который в свою очередь содержит виртуальные методы.

Более того VMT родителя повторяется в VMT наследника с добавлением в нее сведений о виртуальных методах наследника, если таковые имеются

Использование таблиц VMT обеспечивает более быстрый поиск требуемого метода, но они и занимают много памяти при больших проектах. При использовании динамических методов таблицы DMT создаются только для тех классов, которые их имеют, т.е. они экономят память, но замедляют поиск.

Page 27: Лекция16_17_Объекты и классы

04/23/23 27

Пример абстрактного класса для рисования• Var ColrBack:Tcolor;• Type • Tviz=class(Tobject)• Canvas:Tcanvas;• ColrLine:Tcolor;• x,y,r:word;• Procedure Ris;virtual;abstract;• Procedure Draw(bl:boolean);• procedure Show;• procedure Hide;• procedure MovTo(dx,dy,dr:integer);• end;

• Метод Ris в родительском классе ничего не делает• Объекты абстрактного класса не создаются!

Page 28: Лекция16_17_Объекты и классы

04/23/23 28

Описание методов абстрактного классаПрорисовка рисунка заданным цветом или

цветом фона• Procedure Tviz.Draw(bl:Boolean);• begin• with Canvas do begin• if bl then begin pen.color:=colrLine;• brush.color:=colrLine end• else begin pen.color:=colrBack;• brush.color:=colrBack end;• ris; //процедура ris что-то рисует• end;•

Page 29: Лекция16_17_Объекты и классы

04/23/23 29

Описание методов абстрактного класса• Procedure Tviz.Show; (показать рисунок)• begin• Draw(true);• end;• Procedure Tviz.Hide; (стереть рисунок)• begin• Draw(false)• end;• procedure Tviz.MovTo; (передвинуть рис)• begin• Hide;• x:=x+dx; y:=y+dy; r:=r+dr;• Show;• end;

Page 30: Лекция16_17_Объекты и классы

04/23/23 30

Класс потомок рисования круга• Unit unit2;• interface• uses Graphics;• var ColrBack:Tcolor;• Type• Tviz=class(Tobject)• <Вставить описание которое приведено выше>• end;• TKrug=class(Tviz)• x1,y1,x2,y2:word;• Constructor Create(x0,y0,r0:word;• colrLine0:Tcolor;canvas0:Tcanvas);• Procedure Ris; override;• end;• . . .

Page 31: Лекция16_17_Объекты и классы

04/23/23 31

Класс потомок рисования круга• implementation• <Описание методов Tviz>• Constructor TKrug.Create;• begin• colrLine:=colrLine0;• canvas:=canvas0;• x:=x0; y:=y0; r:=r0;• end;• Procedure Tkrug.ris;• Begin• x1:=x-r; x2:=x+r; y1:=y-r; y2:=y+r;• Canvas.Ellipse(x1,y1,x2,y2);• end; • End.

Page 32: Лекция16_17_Объекты и классы

04/23/23 32

Программа рисования• unit Unit1;• interface• uses• Windows, Messages, SysUtils, Variants, Classes,

Graphics, Controls, Forms, Dialogs, ExtCtrls, ComCtrls, StdCtrls;

• type• TForm1 = class(TForm)• Button1: TButton;• Image1:TImage;• . . . . . . . . . • procedure Button1Click(Sender: TObject);• . . . . . . . . . • end;• var• Form1: TForm1;• implementation• uses unit2, Clipbrd;

Page 33: Лекция16_17_Объекты и классы

04/23/23 33

• var krug:Tkrug; Программа рисования• okno1:Timage;• pxm1,pym1:word;• xo,yo,ro:word;• procedure TForm1.Button1Click(Sender: TObject);• begin• okno1:=Form1.Image1;• colrBack:=clWhite;• pxm1:=okno1.ClientWidth;• pym1:=okno1.ClientHeight;• with okno1.canvas do begin• pen.color:=colrBack;• brush.color:=colrBack;• Rectangle(0,0,Pxm1,Pym1);• end;• xo:=pxm1 div 2; yo:=pym1 div 2; ro:=10;• Krug:=Tkrug.Create(xo,yo,ro,clBlack,okno1.canvas);• krug.Show; • End;

Page 34: Лекция16_17_Объекты и классы

04/23/23 34

Перемещения круга• procedure TForm1.Button2Click(Sender: TObject);• begin //Увеличить круг• Krug.MovTo(0,0,3);• end;• procedure TForm1.Button3Click(Sender: TObject);• begin //уменьшить• Krug.MovTo(0,0,-3);• end;• procedure TForm1.Button4Click(Sender: TObject);• begin //двигать вправо-вверх• Krug.MovTo(3,3,0);• end;• procedure TForm1.Button5Click(Sender: TObject);• begin //двигать влево-вниз• Krug.MovTo(-3,-3,0);• end;

Page 35: Лекция16_17_Объекты и классы

04/23/23 35

Печать картинки и уничтожение объекта

• procedure TForm3.Button8Click(Sender: TObject);• begin //только для TImage !!! сохранить

картинку• Clipboard.Assign(Image1.Picture);• end;• procedure TForm1.BitBtn6Click(Sender: TObject);• begin• krug.Free;• end;

Page 36: Лекция16_17_Объекты и классы

04/23/23 36

Круг+прямоугольник (тело)• Interfase• TKrPr=class(Tkrug)• dy1:word;• Constructor Create(x0,y0,r0,dy0:word; • colrLine0:Tcolor;canvas0:Tcanvas);• Procedure ris; override;• end;• Implementation• Constructor TKrPr.create;• begin• dy1:=dy0;• Inherited Create(x0,y0,r0,colrLine0,canvas0);;• end;• Procedure TkrPr.ris;• begin• Inherited ris;• Canvas.Rectangle(x1,y2,x2,y2+dy1);• end;

Page 37: Лекция16_17_Объекты и классы

04/23/23 37

Движение тела

Создадим:Krpr:= Tkrpr.Create(xo,yo,ro,4*ro,clBlack,okno1.canvas); Krpr.show;Двигаем:

• procedure TForm3.Button6Click();• begin• //ход конем• krpr.MovTo(10,0,0);• okno1.Update;• sleep(200);• krpr.MovTo(0,5,0);• end;

Page 38: Лекция16_17_Объекты и классы

04/23/23 38

Демонстрация конец