Btn: TButton; //Переменная для кнопки




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

Объявление класса, создание экземпляров класса

Цель работы: научиться решать задачи на создание объектов-наследников на Object Pascal в инструментальной среде разработки Delphi. Овладение практическими навыками создания и работы с наследниками.

Базовые понятия

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

Каждый объект в ООП имеет свой тип (класс). Класс представляет собой тип данных, имеющий в составе:

· Свойства - Параметры объекта (конечно, не все, а только необходимые в программе).

· Методы - Действия, которые можно выполнять над объектом такого типа, или которые сам объект может выполнять.

Объектные типы данных называют классами, а их экземпляры — объектами.

Класс обычно описывает сущность, моделируемую в программе.

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

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

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

Объявление свойства выполняется с помощью зарезервированного слова property.

Ключевые слова read и write называются спецификаторами доступа. После слова read указывается поле или метод, к которому происходит обращение при чтении (получении) значения свойства, а после слова write — поле или метод, к которому происходит обращение при записи (установке) значения свойства.

Если один из спецификаторов доступа опущен, то значение свойства можно либо только читать (задан спецификатор read), либо только записывать (задан спецификатор write).

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

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

Использование методов для получения и установки свойств позволяет проверить корректность значения свойства, сделать дополнительные вычисления, установить значения зависимых полей и т.д.

Кроме обычных свойств в объектах существуют свойства-массивы (array properties). Свойство-массив — это индексированное множество значений.

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

Свойства-массивы имеют два важных отличия от обычных массивов:

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

В механизме наследования можно условно выделить три основных момента:

  • наследование полей;
  • наследование свойств;
  • наследование методов.

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

Наследование свойств и методов имеет свои особенности.

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

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

В языке Delphi существует предопределенный класс TObject, который служит неявным предком тех классов, для которых предок не указан. Это означает, что объявление Класс TObject выступает корнем любой иерархии классов. Он содержит ряд методов, которые по наследству передаются всем остальным классам. Среди них конструктор Create, деструктор Destroy, метод Free и некоторые другие методы.

 

Практическая часть

Создадим класс TShar.

После блока uses добавьте строки

uses …;

 

type TShar= class

constructor Create(C:TCanvas);

procedure DrawMe(C:TCanvas);

Private

x,y:integer; //Это координаты фигурки

dx,dy:integer; //Это приращение скорости по направлению x и y

col:integer; //Цвет фигурки

end;

 

Итак, мы создали класс, который описывает фигурку, которая будет двигаться по форме. Метод DrawMe рисует фигурку на TCanvas. После ключевого слова implementation добавьте код метода

 

procedure TShar.DrawMe(C:TCanvas); //Рисуем кружок

Begin

form1.Canvas.Brush.color:=col;

C.Pen.Color:=col;

C.Ellipse(x-5,y-5,x+5,y+5);

end;

 

При создании объекта (экземпляра класса) вызывается конструктор Create. В теле конструктора можно задать начальные значения внутренних переменных

constructor TShar.Create();

Begin

Randomize; //Сбрасываем генератор случайных чисел

x:=Random(150); //Записываем в x случайное от 0 до 150

y:=Random(200); //Записываем в y случайное от 0 до 150

dx:=2-Random(4); //dx “скорость движения” фигуры по оси x

dy:=2-Random(4); //dy “скорость движения” фигуры по оси y

if dx=0 then dx:=1; //если скорость нулевая присваиваем 1

if dy=0 then dy:=1;

col:=Random(255*255); //Задаем случайный цвет

end;

 

Код класса готов. Объявим объект s. В области var добавьте строку.

Var

n1,i:integer; //В переменную n будем сохранять число объектор.

Form1: TForm1;

s1: array [1..20] of TShar; //Массив для 20 фигурок

 

Добавьте на форму Кнопку(TButton) и таймер(TTimer). Установите инспекторе объектов свойство таймера Enabled в false, а Interval в 50. При нажатие на кнопке на форм должен появляться новая фигурка.

 

Щелкните по кнопке и добавьте код

procedure TForm1.Button1Click(Sender: TObject);

Begin

if n1=20 then exit; //В переменной n1 содержится число фигурок на форме.

//Если на форме уже 20 фигурок,

//то просто выходим не создавая новую.

n1:=n1+1; //Увеличиваем счетчик фигурок на 1

s1[n1]:=TShar.Create(); //Создаем новый элемент массива

Timer1.Enabled:=true; //Запускаем таймер.

end;

 

Дважды щелкните на значке таймера.

procedure TForm1.Timer1Timer(Sender: TObject);

Begin

//Следующие две строки закрашивают белый квадратик

form1.Canvas.Brush.color:=clwhite;

form1.Canvas.FillRect(0,0,160,210);

//Проходимся по всем элементах массива

for i:=1 to n1 do begin

s1[i].DrawMe(form1.Canvas); //Вызываем метод, рисующий фигуру

end;

end;

 

Щелкните по форме и объявите события OnFormCreate, OnFormDestroy

procedure TForm1.FormCreate(Sender: TObject);

Begin

n1:=0;

end;

 

procedure TForm1.FormDestroy(Sender: TObject);

Begin

for i:=1 to n1 do begin

s1[i].Free;

end;

end;

 

Запустите программу. При нажатие на кнопку на форме должны появляться кружочки. Заставим их двигаться. Зададим в классе TShar метод MoveMe, который будет изменять координаты x и y фигурки на значения dx и dy.

Добавим в объявление класса строку

type TShar=class

constructor Create(C:TCanvas);

procedure DrawMe(C:TCanvas); virtual;

procedure MoveMe;

private

x,y:integer;

dx,dy:integer;

R,col:integer;

end;

 

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

procedure TShar.MoveMe;

Begin

x:=x+dx;

y:=y+dy;

if x<0 then begin x:=1; dx:=-dx; end; //Выход за левую границу

if y<0 then begin y:=1; dy:=-dy; end; //Выход за верхнюю границу

if x>150 then begin x:=150; dx:=-dx; end; //Выход за правую границу

if y>200 then begin y:=200; dy:=-dy; end; //Выход за нижнюю границу

end;

 

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

procedure TForm1.Timer1Timer(Sender: TObject);

Begin

form1.Canvas.Brush.color:=clwhite;

form1.Canvas.FillRect(0,0,160,210);

for i:=1 to n1 do begin

s1[i].MoveMe;

s1[i].DrawMe(form1.Canvas);

end;

end;

 

Запускаем программу. Теперь после запуска программы фигурки будут двигаться. Создадим новый класс TCube наследник класса TShar. Переопределим в классе потомке TCube метод DrawMe, чтобы он рисовал не круги, а прямоугольники. Для этого:

1. В классе TShar при объявлении метода DrawMe используем слово virtual.

type TShar=class

constructor Create(C:TCanvas);

procedure DrawMe(C:TCanvas); virtual;

procedure MoveMe;

private

x,y:integer;

dx,dy:integer;

col:integer;

end;

 

2. Добавим новый класс TCebe указав в качестве класса-предка TShar, а при объявлении метода DrawMe используем слово override.

type TCube=class(TShar)

procedure DrawMe(C:TCanvas); override;

end;

 

3. Добавим метод DrawMe для класса TCube.

procedure TCube.DrawMe(C:TCanvas);

Begin

form1.Canvas.Brush.color:=col;

C.Pen.Color:=col;

c. FillRect (x-5,y-5,x+5,y+5);

end;

 

4. Обновим область задания переменных. Добавим массив s2 для квадратов, n2 – счетчик квадратов.

Var

n1, n2,i:integer;

Form1: TForm1;

s1: array [1..20] of TShar;

s2: array [1..20] of TCube;

 

5. Обновим таймер

procedure TForm1.Timer1Timer(Sender: TObject);

Begin

form1.Canvas.Brush.color:=clwhite;

form1.Canvas.FillRect(0,0,160,210);

//Двигаем и рисуем круги

for i:=1 to n1 do begin

s1[i].MoveMe;

s1[i].DrawMe(form1.Canvas);

end;

//Двигаем и рисуем квадраты

for i:=1 to n2 do begin

s2[i].MoveMe;

s2[i].DrawMe(form1.Canvas);

end;

end;

 

6. А также методы FormDestroy и FormCreate

procedure TForm1. FormDestroy (Sender: TObject);

Begin

for i:=1 to n1 do begin

s1[i].Free;

end;

for i:=1 to n2 do begin

s2[i].Free;

end;

end;

 

procedure TForm1. FormCreate (Sender: TObject);

Begin

n1:=0;

n2:=0;

end;

 

7. Добавим на форму еще одну кнопку, которая будет добавлять квадратик. Ее код аналогичен кнопке TForm2.Button1Click

procedure TForm2.Button2Click(Sender: TObject);

Begin

if n2=20 then exit;

n2:=n2+1;

s2[n2]:=TCube.Create(Form1.Canvas);

Timer1.Enabled:=true;

end;

 

Заставим фигурки менять цвет при щелчке по ним мышкой. В классе TShar добавим метод PushME (x1,y1:integer) в который будем передавать координаты щелчка мышки и если эти координаты окажутся внутри прямоугольника, ограничивающего фигуру, будем менять значение переменной col, которая отвечает за цвет.

 

1. Объявим метод в классе

type TShar=class

constructor Create(C:TCanvas);

procedure DrawMe(C:TCanvas); virtual;

procedure MoveMe;

procedure PushME(x1,y1:integer);

private

x,y:integer;

dx,dy:integer;

col:integer;

end;

 

2. Добавим код метода PushMe для класса TShar.

procedure TShar.PushME(x1,y1:integer);

Begin

if (x1>x-5)and(x1<x+5)and (y1>y-5)and(y1<y+5) then col:=Random(255*255);

end;

 

3. Перейдем в режим дизайна формы, щелкнем на форме, в инспекторе объектов выберем событие OnMouseDown. Вызовем метод PushME для всех созданных фигур.

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

Begin

for i:=1 to n1 do begin

s1[i]. PushME (x,y);

end;

for i:=1 to n2 do begin

s2[i]. PushME (x,y);

end;

end;

 

4. Запустите программу. Хотя мы написали метод PushME только для класса TShar, он автоматически наследуется классом TCube, поэтому прищелчке мышкой по квадратикам, они тоже будут менять цвет.

Ход работы:

Задание 1: в классе TForm1 используются 4 одноименных метода Сlose. Лишь один из них - унаследованный метод без параметра выполняет свои основные функции - закрывает окно. Три других отличаются набором параметров и выводят сообщение в заголовок окна.

Ход работы: Поместите на пустую форму четыре кнопки TButton и напишите такие обработчики их событий OnClick:

procedure TForm1.ButtonlClick(Sender: TObject);

begin

Close('Строка символов')

end;

procedure TForm1.Button2Click(Sender: TObject);

begin
Close(123)

end;


procedure TForm1.ButtonSClick(Sender: TObject);

begin
Close (20,300);

end;

procedure TForm1.Button4Click(Sender: TObject);

begin
Close
end;

 

Теперь в раздел private класса Tform1 вставьте три таких объявления методов close:

private
{Private declarations}

procedure Close(S: String);reintroduce;overload;

procedure Close(I: Integer);reintroduce;overload;

procedure Close(I,J: Integer);reintroduce;overload;

 

И, наконец, в разделе implementation поместите описания объявленных методов:


procedure TForm1.Close(S: String);

begin

Caption:= S

end;

procedure TForm1.Close(I: Integer);

begin
Caption:= IntToStr(I)

end;

procedure TForm1.close(I,J: Integer);

begin
Caption:= IntToStr(i*j)

end;

Теперь после запуска программы три первые кнопки будут вызывать методы close класса Tform1 и менять заголовок окна, в то время как кнопка Button4 обратится к методу close родительского класса TForm и закроет окно.

Задание 2: на форме вашей программы находится кнопка "Дополнительно...", при нажатии на которую ваша форма должна увеличиться в размерах и на ней должны появиться дополнительные элементы управления.

Установите на форму кнопку Button1 (Caption = "Дополнительно...")

Щелкните на кнопке Button1 и внесите в появившуюся заготовку следующий код:

Листинг:

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

TForm1 = class(TForm)

Button1: TButton;

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

procedure MyAction(Sender:TObject);

public

{ Public declarations }

end;

var

Form1: TForm1;

btn: TButton; //Переменная для кнопки



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-06-03 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: