Презентація на тему «Класи в Pascal»

Класи в Pascal
	Об’єкти реального світу можна описати за допомогою величин, що характеризують стан об’єкта та його поведінку (що робить об’єкт або що з ним можна робити), поведінка змінює стан об’єкта. Для адекватного моделювання реального світу в програмах, потрібно мати сутність, яка поєднує дані та алгоритм.
boolean
integer (const)
real


real


    procedure
    function


Unit Pen_unit;
type Tpen = class
	private
		ready: boolean;
		price: real;
		colour: TColor;
		paintColour: TColor;
		paintSupply: real;
	public
		function isReady: boolean;
		procedure SwitchOn;
		procedure SwitchOff;

дані

методи

оголошення
Оголошення класу відбувається в модулі, але це можна робити і в головній програмі.
	procedure Write (aWord: string);
	procedure Rechange (aPaint: TColor);
	constructor Create (a, b: TColor; p, s: real);
	end;
Implementation
begin
function Tpen.isReady: boolean;
	begin
	     result := ready;
	end;
procedure Tpen.switchOn
	begin
	     ready:=paintSupply > 0;
	end;
…
end.
Program prg_1;
   uses Pen_unit;
	var a: Tpen;
begin
	a:=Tpen.Create(cOrange, cBlack; 2.5, 125.7);
	a.Write(‘Hello, World!’);
	a.switchOff;
	a.Free;  	      звільнити динамічну пам’ять
end.
	В об’єктній моделі ObjectPascal усі екземпляри класів динамічні. Змінна об’єктного типу – це неявний вказівник або посилання на динамічну пам’ять, де можна розташувати екземпляр класу.
Екземпляр створюють за допомогою конструктора і знищують за допомогою деструктора. Кожен екземпляр класу має окрему пам’ять і власний набір полів. Усі екземпляри класу поділяють єдиний набір методів, оголошених у класі.

constructor Tpen.Create(a, b: Tcolor; p, s: real);
  begin  colour:=a;
	  paintColor:=b;
	  if    p>=1.0   then   price:=p
			 else   price:=1.0;
	  if s>=100.0   then paintSupply:=s
			 else paintSupply:=100.0;
	  ready:=false;
end;
Інкапсуляція - обмеження доступу до даних
	Це дозвіл доступатися до спільних даних обмеженій кількості методів, доступ для всіх організовується за посередництва відповідальних за це методів. 

Unit shape_1;
Interface
Type Trect = class(TObject)
	private	a, b: real;
	public
	   	constructor Create(x, y: real);
	  	destructor Destroy;
		function square: real;
	   	function Perym: real;
   Procedure WriteOut;

Implementation

begin
    constructor Trect.Create(x, y: real);
         begin a:=x; b:=y; end;
     destructor Trect.Destroy;
	       begin writeln(‘Said “Bye”’); end;
	procedure Trect.writeOut;
		begin writeln(a, b, ‘Rectangle’); end;
	function  Trect.Sguare: real;
		begin result:=a*b; end;
	function TRect.Perym: real;
		begin
			result:=2*(a+b);
		end;
constructor TRect.Create;
begin
	a:=3;
	b:=4;
end;
end.
Конструктор задає значення полів об’єкта, вони можуть бути (початкові значення) в тексті конструктора або передані через параметри. Імена параметрів  повинні відрізнятися від імен полів.
Деструктор – це метод, відповідальний за коректне звільнення пам’яті від екземпляру класу.
Program p_1;
	uses Shape_1;
	var 		s:array [1…100] of TRect;
			i:integer;
			m:real;
	begin
		…
		m:=s[1].Square;
		for   i:=2 to 100 do
		if s[i].Square>m then
			m:=s[i].Square
		…
	end.
Якщо частина коду написана двічі, виносимо її в окремий метод.
TrectB: Trect + getB, setB
	unit shape_2
		interface
			uses shape_1
		type
			TRectB = class(TRect);
Клас отримує (успадковує)  від поперднього класу всі поля і наслідує їх функціональність.
public
	function getB:real;
	procedure setB(y; real);
	procedure writeOut(t:textfile);
end;
implementation
	function TRectB.getB:real;
		begin
		result:=b;
		end;

procedure TRuctB.setB(y:real);
	begin
		b:=y; calls;
	end;

procedure writeOut(t:textfile);
	begin
		writeln(t, ‘Advanced Rect’, a, ‘x’, b);
	end;

private діє разом з поділом на unit. Доступ ззовні модуля заборонено всім без винятку, всередині модуля дозволено підкласам. Для того, щоб підкласи базового класу мали доступ до окремих полів даних, їх розташовують в області доступу protected.
Program p2;
	uses shape_1; shape_2;
	var	p:Trect;
		q:TRectB;
	begin
		p.TRect.Create;
		q:=Trect.	Create(7, 12);
		q.setB(0.5)
		if p.square<q.square
		then p.writeOut(output)
		else q.writeOut(output)
		p.Free;
		q.Free;
	end.
прямокутник розміром 3×4
	Метод WriteOut у класі TRect оголошено звичайним чином як статичний метод такий, як square, perym,…тому в коді деструктора виклик WriteOut прив’язується на етапі компіляції до методу TRect.WriteOut, це називають раннім зв’язуванням.
	Для того, щоб деструктор викликав метод WriteOut потрібного класу, його оголошують віртуальним.
	Виклики віртуальних методів виконують за допомогою пізнього зв'язування, що відбувається на етапі виконання програми.
	Клас Tobject є базовим. Усі інші класи є його нащадками. Free – метод, який звільняє динамічну пам'ять. Destroy – деструктор.
	Підклас успадковує від базового класу усі без винятку поля класу і наслідує його поведінку, це означає, що екземпляри підкласу здатні опрацьовувати такі ж повідомлення, як і екземпляри базового. Підкласові доступні усі public і protected методи базового класу, тому екземпляри підкласу можуть без перешкод і без змін використовувати методи базового класу. Дуже часто підклас змінює поведінку базового (перевизначає окремі методи) і/або доповнює (додає нові методи).
	
Взаємозвязки між базовим і похідними класами
Для перевизначення методів є дві можливості:
для звичайних (статичних) методів дозволено використовувати довільну сигнатуру, тобто, метод з тим самим іменем у підкласі може мати інший набір параметрів;
Віртуадбні методи перевизначають завжди з ттою самою сигнатурою.
var c, a, b: Trect;
	begin
		a:=TRect.Create(3, 4);
		b:=TRect.Create(4, 3);
		if a.Square > b.Square
		   then c:=a
		   else c:-b
		c.WriteOut(output);
		…
	end.

копіювання  вказівника
Отримання копії об'єкта
	Щоб отримати копію об'єкта, необхідно створити додатковий конструктор, який прийматиме параметром об'єкт того ж класу:
d:=TRect.CopyCreate(a)


Раннє і пізнє зв'язування
Приклад: купівля кілограму апельсинів.
Ми заздалегідь знаємо, що нам потрібно купити 1 кг апельсинів. Тому ми беремо невеликий пакет, небагато, але достатньо грошей, щоб вистачило на цей кілограм.
Виходячи з будинку, ми не знаємо чого і скільки нам потрібно купити. Тому ми беремо машину(а раптом буде багато всього і важко нести?), запасаємося пакетами великих і малих розмірів і беремо якомога більше грошей. Їдемо на ринок і з'ясовується, що потрібно купити тільки 1 кг апельсинів.
	При застосуванні раннього зв'язування, ми ніби говоримо компілятору: "Я точно знаю, чого я хочу. Тому жорстко(статично) зв'язуй усі виклики функцій". При застосуванні механізму пізнього зв'язування ми говоримо компілятору: "Я доки не знаю, чого я хочу. Коли прийде час, я повідомлю, що і як я хочу".

Висновки: 
	Таким чином, під час раннього зв'язування методи зв'язуються при першій слушній нагоді. У пізньому зв'язуванні реалізований спеціальний механізм, який визначає, як відбуватиметься зв'язування, що викликається і викликає методи, коли виклик буде зроблений фактично.
Очевидно, що швидкість і ефективність при ранньому зв'язуванні вищі, ніж при використанні пізнього зв'язування. У той же час, пізнє зв'язування забезпечує деяку універсальність зв'язування.


	Адресу динамічного методу міститиме таблиця того класу, де він визначений
		TSquare = class(TRect)
		constructor 	Create(x: real);
		procedure WriteOut(var t:textfile);
	end;
//public можна упустити.
		constructor TSquare.Create(x: real );
			begin
				inherited
				Create(x, x);
			end;
override
Name() – overload
Name(x) – override




			Tshape

		TRect		TCircle


	TRectB	TSquare


a, s
P-4a
S=a2

TRect
b
P=2(a+b)
S=ab

TRectB
Tshape = clas(TObject)
private
	s:real;
protected procedure Calc S; virtual; abstract;
public
	function Perym: real; virtual; abstract;
	function Square: real;
	procedure WriteOut(var T: textfile); virtual; absract;
	destructor Destroy; override;
	end;

	function TShape Square: real;
		begin
			result:=s;
		end;
Tshape 3d

		    TPiramide     TConus  TCylindr   TParalelepiped  
base: TShape
Tshape 3d = class(TObject)
	private
			base: Tshape;
			        h: real;
end;

Циліндр	Конус		Піраміда	Паралелепіпед
V=Sосн.h		V =    Sосн.h	V=    Sосн.h	       V=Sосн.h	
…


	Кожен клас повинен містити свій конструктор.

TShape 3d
	base: TShape;
	h: real;


	base.Square; v; a
	side.Square; v; a
	surf.Square; v; a
	Volume; v; a
	WriteOut; v; a
function TShape3d.base.square: real;
	begin
		result:=base.Square();
	end;
	constructor     TCylindr.Create(a, b: real);
		begin
			base:=TCircle.Create(a);
			h:=b;
		end;
	constructor  TParalelepiped.Create(x, y, z: real);
		begin
			base:=TRect.Create(x, y);
			h:=z;
		end;
function TDirectShape.volume: real;
	begin
		result:=base.square*h;
	end;

Завдання:

	Задано виміри 12 різних об'ємних фігур, потрібно надрукувати інформацію про кожного з них, знайти фігуру з найбільшим
об'ємом і з найменшою повною
поверхнею.
const n=12;
type mas=array[1…n] of TShape3d
 var a: mas;
k, i: integer;
x, y, z: real;
	for i:=1 to n do
		A[i].writeOut;
begin
	for i:=1 to n do
	begin
		read(k);
		case k of
	Cylindr: begin
		readln(x, y);
		A[i]:=Tcylindr.Create(x, y);
Paralelepiped: begin
		      readln(x, y, z);
		      A[i]:= Tparalelepiped.Create(x, y, z);
		      end;
	…   end;
…
end.

TRectAB = class;
private a,b: real;
public
	function getB(): real;
	procedure setB(x: real);
	function Square(): real;
	procedure WriteOut();
constructor Create(x, y: real);
end;
…
begin
	readln(size);
	R:=TRectAB.Create(size, 7);
	R.setA(R.getA + z);
TRect_AB = class
	private
		Fa, Fb: real;	// field
	protected
		function getA(): real;
		function getB(): real;
		procedure setA(x: real);
		procedure setB(x: real);
public
	constructor Create(x; y: real);
	function Square(): real;
	property a: real:  read getA write setA;
	property b: real:  read getB  write setB;
end;
	Property описує інтерфейсний елемент, його використовують для неявного виклику методів.

begin
	R:=TRect_AB.Create(size, 7);
	R.a:=R.a+2;

	Property – новий спосіб доступу. Ключові слова read і write вказують чи буде для властивості доступ для читання і для запису відповідно. Кожна з цих частин може бути відсутня