Электронный учебник

§ 48. Создание объектов в программе

Класс Дорога

Объектно-ориентированная программа начинается с описания классов объектов. Класс в программе — это новый тип данных. Как и структура (см. § 39), класс — это сложный тип данных, который может объединять переменные различного типа в единый блок. Однако, в отличие от структуры, класс содержит не только данные, но и методы работы с ними (процедуры и функции).

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


Поле — это переменная, принадлежащая объекту.


Значения полей описывают состояние объекта, а методы — его поведение.

Описание класса Дорога в программе на объектной версии Паскаля (здесь имеется в виду FreePascal или Delphi) выглядит так:

type TRoad = class

Length: real;

Width: integer; end;

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

Буква «Т» в начале названия класса — это сокращение от слова type.

Если мы хотим работать с объектом класса TRoad, в программе нужно объявить соответствующую переменную:

var road: TRoad;

Однако и это ещё не объект, а ссылка (указатель), т. е. переменная, в которой можно сохранить адрес любого объекта класса TRoad. Чтобы создать сам объект в памяти, нужно вызвать специальный метод Create, который называется конструктором. Адрес нового объекта записываем в переменную road:

road:=TRoad.Create;

Созданный объект относится к классу TRoad, поэтому его называют экземпляром класса TRoad.

При описании класса мы ничего не говорили о методе Create. Он добавляется ко всем классам по умолчанию, при его вызове все переменные объекта заполняются нулями.


Конструктор — это метод класса, который вызывается для создания объекта этого класса.


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

road.Length:=60; road.Width:=3;

Полная программа, которая создаёт объект «дорога» (и больше ничего не делает), выглядит так:

{$mode objfpc} type TRoad = class

Length: real;

Width: integer; end;

var road: TRoad; begin

road:=TRoad.Create; road.Length:=60; road.Width:=3 end.
Хотя стандарта на этот счёт нет, так сделано во всех объектных реализациях Паскаля.

Строка {$mode objfpc} по форме похожа на комментарий, потому что заключена в фигурные скобки. Однако для компилятора это команда перейти в режим работы с объектами (англ. mode — режим; object — объект; FPC — Free Pascal Compiler — свободно распространяемый компилятор Паскаля).

Начальные значения полей можно задавать прямо при создании объекта. Для этого нужно добавить в описание класса новый конструктор. Конструктору будет передаваться два параметра — начальные значения длины и ширины дороги:

type TRoad = class

Length: real;

Width: integer;

constructor Create(lengthO: real;

widthO: integer)

end;

Реализация (программа) конструктора может выглядеть так:

constructor TRoad.Create(lengthO: real;

widthO: integer);

begin

if length0>0 then

Length:=lengthO else Length:=1; if width0>0 then

Width:=widthO else Width:=1;

end;

Здесь проверяется правильность переданных параметров, чтобы по ошибке длина и ширина дороги не оказались нулевыми или отрицательными. Теперь создавать объект будет проще:

road:=TRoad.Create (60, 3) ;

Длина этой дороги — 60 единиц, она содержит 3 полосы.

Таким образом, класс выполняет роль «фабрики», которая «выпускает» (создаёт) объекты «по чертежу» (описанию класса) при вызове конструктора.
 

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

Машина

Теперь можно описать класс Машина (в программе назовём его ТСаг). Объекты класса ТСаг имеют три свойства и один метод — процедуру move. Координата X и скорость V — это вещественные значения, а номер полосы Р — целое, type ТСаг = class

X, V: real;

Р: integer; road: TRoad; procedure move;

constructor Create(roadO: TRoad;

pO: integer; vO: real);

end;

Так как объекты-машины должны обращаться к объекту «дорога», в область данных включено дополнительное поле road. Конечно, это не значит, что в состав машины входит дорога. Напомним, что это только ссылка, и сразу после создания объекта-машины нужно записать в неё адрес заранее созданного объекта «дорога». Эту привязку удобно сделать прямо в конструкторе, при создании объекта. Заодно мы определяем полосу движения и скорость, а начальная координата X автоматически устанавливается равной нулю:

constructor ТСаг.Create(roadO: TRoad;

pO: integer; vO: real);

begin

road:=roadO; P:=pO; V:=vO; end;

Теперь займёмся реализацией (программированием) метода move (англ. move — двигаться). В этом методе нужно вычислить новую координату X машины и, если она находится за пределами дороги, установить её в ноль (машина появляется слева на той же полосе). Изменение координаты при равномерном движении описывается формулой

X = Х0 + V • At,

где Х0 и X — начальная и конечная координаты, V — скорость, a At — время движения. Вспомним, что любое моделирование физических процессов на компьютере происходит в дискретном времени, с некоторым интервалом дискретизации. Для простоты мож

но измерять время в этих интервалах, а за скорость V принять расстояние, проходимое машиной за один интервал. Тогда метод move, описывающий изменение положения машины за один интервал (At = 1), может выглядеть так:

procedure TCar.move; begin

X:=X+V;

if X > road.Length then X:=0; end;

Основная программа

В основной программе объявим массив объектов-машин:

const N=3;

var cars: array [1..N] of TCar;

Как вы помните, это ещё не объекты, а ссылки — переменные, в которые можно записать адреса объектов класса ТСаг. Теперь нужно создать сами объекты:

var i: integer;

for i:=l to N do

cars[i]:=TCar.Create(road, i, 2.0*i);

При вызове конструктора задаются три параметра: адрес объекта «дорога» (его нужно создать до выполнения этого цикла), номер полосы и скорость. В приведённом варианте машина на полосе с номером i движется со скоростью 2i единиц за один интервал моделирования.

Сам цикл моделирования получается очень простой: на каждом шаге вызывается метод move для каждой машины:

repeat

for i:=l to N do cars[i].move; until keypressed;

Этот цикл закончится тогда, когда пользователь нажмёт любую клавишу и функция keypressed, расположенная б модуле Crt, вернет значение True.

Полностью основная программа выглядит так:

us е: s С: лг -t ;

cj.onst- 1ST =    3    р

-v-3t:rr 2COSLci:    UTESlo    sl    ci;

cars: array [1..N] of TCar; i: integer;

begin

road:=TRoad.Create(60, N) ; for i:=l to N do

cars[i]:=TCar.Create(road, i, 2.0*i); repeat

for i:=l to N do cars[i].move; until keypressed;

end.

Можно ли было написать такую же программу, не используя объекты? Конечно, да. И она получилась бы короче, чем наш объектный вариант (с учётом описания классов). В чём же преимущества ООП?

Мы уже отмечали, что ООП — это средство разработки больших программ, моделирующих работу сложных систем. В этом случае очень важно, что при использовании объектного подхода:

•    основная программа, описывающая решение задачи в целом, получается простой и понятной; все команды напоминают действия в реальном мире («машина № 2, вперёд!»);

•    разработку отдельных классов объектов можно поручить разным программистам, при этом каждый может работать независимо от других;

•    если объекты классов Дорога и Машина понадобятся в других разработках, можно будет легко использовать уже готовые классы.

 

 

Вопросы и задания
1.    Что такое поле в описании класса объекта?

2.    Как объявляется класс объектов в программе?

3.    Как объявляется переменная для работы с объектом некоторого класса? Что в ней хранится?

4.    Как в памяти создаётся экземпляр класса (объект)?

5.    Что такое конструктор?

6.    Что такое точечная нотация? Как она используется при работе с объектами?

7.    Как можно задать начальные значения для полей объекта?

8.    Почему в методе ТСаг.move (пример, разобранный в параграфе) не объявлены переменные X и V?

9.    Сравните преимущества и недостатки решения рассмотренной задачи «классическим» способом и с помощью ООП. Сделайте выводы.

 

 

Подготовьте сообщение

а)    «Классы в языке Си»

б)    «Классы в языке Javascript»

в)    «Классы в языке Python»


 

Возрат в главу

 

Block title

Вход на сайт

Поиск

Календарь

«  Декабрь 2024  »
ПнВтСрЧтПтСбВс
      1
2345678
9101112131415
16171819202122
23242526272829
3031

Архив записей

Статистика


Онлайн всего: 1
Гостей: 1
Пользователей: 0