· Каждый раз, когда структура данных должна быть динамической и содержать вложенные структуры, следует применять средства объектно-ориентированного программирования.
· Объектно-ориентированное программирование основано на трех главных принципах – инкапсуляции, наследовании и полиморфизме. Инкапсуляция – это объединение данных и поведения (т.е. методов) в одном пакете (т.е. объекте). Наследование означает автоматическое включение всех полей, свойств и методов родительского класса в состав дочернего класса. Полиморфизм означает возможность переопределения метода в дочернем классе.
· Объектная переменная является указателем на область памяти, в которой хранятся данные объекта. Однако в отличие от обычных указателей, объектную переменную для доступа к объекту не нужно разадресовывать.
· В системе Delphi поле – это переменная, входящая в состав объекта, а свойство – это интерфейс между данными, хранящимися в поле, и остальной частью программы. Методом называется подпрограмма, ассоциированная с классом.
· Класс является типом объекта.
· Класс TObject является базовым классом Delphi. Все классы (в том числе компоненты и элементы управления) являются потомками класса TObject. Если родительский класс не задан, то по умолчанию родительским является класс TObject.
· Синтаксис объявления свойства имеет вид
property имя_свойства: тип [read get-метод] [write set-метод];
В каждое объявление свойства должен входить, как минимум, один спецификатор чтения или записи.
· Метод get читает значения поля, а метод set изменяет его. Определение методов get и set имеет следующий синтаксис:
function имя_класса. get_ метод: тип;
//Обратите внимание: тип должен совпадать с типом поля
begin
get_ метод:= имя_поля;
end;
procedure имя_класса. set_метод (значение: тип);
//Обратите внимание: тип значения должен совпадать с типом
//поля свойства
begin
имя_поля:= значение;
end;
Метод get вызывается каждый раз, когда в исходном коде выражение объектная _ переменная. имя_свойства встречается в правой части оператора присваивания или в любом операторе, не являющемся оператором присваивания. Метод set вызывается при каждой встрече в исходном коде выражения объектная _ переменная. имя_свойства в левой части присваивания.
· Для создания и удаления объектов используются специальные методы, называемые конструктором и деструктором. Их синтаксис отличается от синтаксиса обычных методов только тем, что они обозначены ключевыми словами constructor и destructor.
constructor имя_класса. Create;
begin
inherited Create;
[ операторы_инициализации ]
end;
destructor имя_класса. Destroy;
begin
[ операторы_завершения ]
inherited Destroy;
end;
При создании объекта все его поля автоматически инициализируются. Значения числовых полей устанавливаются в нуль, строковым полям присваивается строка null, а объектным полям – nil. в конструкторе программист может инициализировать поля объекта по-другому.
· Ключевое слово self обозначает переменную, присутствующую в каждом методе по умолчанию и ссылающуюся на объект, которому принадлежит этот метод. Переменная self полезна для передачи информации о текущем объекте в другую подпрограмму или для вызова другого метода класса.
· Объекты являются динамическими структурами. Для объявления новой объектной переменной используется синтаксис
var
объектная _ переменная: имя_класса;
Прежде чем объектная переменная может быть использована, необходимо создать объект:
объектная _ переменная:= имя_класса.Create;
· Для удаления объекта используется оператор
объектная _ переменная. Free;
Для этого рекомендуется использовать метод Free, а не Destroy, так как метод Destroy генерирует для объектов nil ошибку.
· Потерянный объект не имеет ссылающейся на него объектной переменной. Появление потерянных объектов может привести к утечке памяти. Помните: объекты являются динамическими структурами. Поскольку объекты создаются программистом, он же должен и удалить их из памяти, чтобы освободить занимаемое ими пространство для других целей.
· С помощью ключевого слова inherited можно вызывать метод родительского класса. Это ключевое слово играет важную роль в реализации принципа полиморфизма.
· Директива overload используется для перегрузки методов. Вызов из метода дочернего класса перегруженного метода влесет активизацию той версии метода, список формальных параметров которой совпадает со списком фактических параметров.
· Необязятельная директива reintroduce подавляет предупреждения компилятора о том, что методы с этим же именем уже объявлены в родительских классах.
Рассмотрим следующий пример. Необходимо реализовать классы и операции над ними для работы с объектами этих классов.
Комплексное число задается своей вещественной и мнимой частями. Реализовать сложение двух комплексных чисел
//-----------------------------------------------------------------------------------------------------
//Имя модуля: Komplex_cl
//Назначение: Объектно-ориентированная реализация комплексных чисел на
// языке Object Pascal
//-----------------------------------------------------------------------------------------------------
unit Komplex_cl;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils;
Type
TKomp=class(TObject)
private
FRe,FIm:real;
Function GetRe:real;
Procedure SetRe(NewRe:real);
Function GetIm:real;
Procedure SetIm(NewIm:real);
public
procedure SetEqual(chislo: TKomp);
constructor Create(NewRe,NewIm:real);
Procedure add(chislo:TKomp);
Function Info:string;
property Re:real read GetRe write SetRe;
property Im:real read GetIm write SetIm;
end;
implementation
//--------------------------------------------------
//Имя метода: GetRe
//Возвращаемое значение: тип real
//Назначение: читает (возвращает) значение поля свойства
//--------------------------------------------------
Function TKomp.GetRe:real;
begin
GetRe:=fRe;
end;
//--------------------------------------------------
//Имя метода: SetRe
//Параметр: NewRe:real
//Назначение: изменяет значение поля свойства на NewRe
//--------------------------------------------------
Procedure TKomp.SetRe(NewRe:real);
begin
fRe:=NewRe;
end;
//--------------------------------------------------
//Имя метода: GetIm
//Возвращаемое значение: тип real
//Назначение: читает (возвращает) значение поля свойства
//--------------------------------------------------
Function TKomp.GetIm:real;
begin
GetIm:=fIm;
end;
//--------------------------------------------------
//Имя метода: SetIm
//Параметр: NewIm:real
//Назначение: изменяет значение поля свойства на NewIm
//--------------------------------------------------
Procedure TKomp.SetIm(NewIm:real);
begin
fIm:=NewIm;
end;
//--------------------------------------------------
//Имя кoнструктора: Create
//Параметры: NewRe,NewIm:real
//Назначение: создает и инициализирует новый объект класса TKomp
//--------------------------------------------------
constructor TKomp.Create(NewRe,NewIm:real);
begin
SetRe(NewRe);
SetIm(NewIm);
//fRe:=NewRe;
//fIm:=NewIm;
end;
//--------------------------------------------------
//Имя метода: SetEqual
//Параметр: chislo: TKomp
//Назначение: устанавливает это число равным числу chislo
// (т.е. копирует chislo)
//--------------------------------------------------
procedure TKomp.SetEqual(chislo: TKomp);
begin
self.SetRe(chislo.FRe);
self.SetIm(chislo.FIm);
end;
//--------------------------------------------------
//Имя метода: Add
//Параметр: chislo: TKomp
//Назначение: складывает chislo с этим числом (по полям)
//--------------------------------------------------
Procedure TKomp.Add(chislo:TKomp);
begin
Re:=Re+chislo.Re;
Im:=Im+chislo.im end;
//--------------------------------------------------
//Имя метода: Info
//Назначение: возвращает строку с описанием объектов класса
//--------------------------------------------------
Function TKomp.Info:string;
begin
result:=FloatToStr(Re)+' + i*'+FloatToStr(Im);
end;
end.
//-----------------------------------------------------------------------------------------------------
//Имя модуля: Komplex_form
//Назначение: Тестовая программа для модуля Komplex_cl
//-----------------------------------------------------------------------------------------------------
unit Komplex_form;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls,
Buttons,Un_kl;
type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Edit3: TEdit;
Edit4: TEdit;
Label3: TLabel;
Label4: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
K, K1, Z:TKomp;
implementation
procedure TForm1.Button1Click(Sender: TObject);
begin
//Создаем объекты К, К1, Z, используя метод Create
K:=TKomp.Create(StrToFloat(Edit1.text),StrToFloat(Edit2.text));
K1:=TKomp.Create(StrToFloat(Edit3.text),StrToFloat(Edit4.text));
Z:=TKomp.Create(0,0);
//Приравниваем объект Z объекту K
Z.SetEqual(K);
//Складываем объекты Z и K1
Z.add(K1);
//Выводим результат, используя процедуру интерактивного вывода
// ShowMessage, отображающую окно сообщения
ShowMessage('Число №1 '+K.info+#13+'Число №2 '+K1.info+#13+'Сумма чисел '+Z.info);
//Удаление объектов К, К1, Z, используя метод Free
Z.Free;
K.Free;
K1.Free
end;
end.
Рис. Создание класса «Комплексное число»
Лабораторная работа №6
Реализовать классы и операции над ними для работы с объектами этих классов.
1. Вектор задан в трехмерном евклидовом пространстве. Задается тройкой своих координат. Реализовать:
a. сложение (вычитание) векторов;
b. скалярное произведение векторов;
c. умножение вектора на скаляр;
2. Строка символов. Реализовать операции:
a. сравнение строк;
b. удаление из строки указанного символа;
c. переворот строки.
3. Ввести класс для работы с прямоугольной матрицей. Реализовать следующие операции:
a. создать инверсную матрицу.
b. сложение (вычитание) двух матриц;
c. умножение матриц.
4. Комплексное число задается своим модулем и углом. Реализовать:
a. сложение (вычитание) чисел;
b. произведение двух чисел;
c. деление чисел;
6. Время задается в формате час.минута.секунда. Реализовать следующие операции (учесть переход через 24 часа):
a. сложение времени и определенного пользователем количества секунд;
b. вычитание из времени указанного пользователем количества секунд;
c. сложение двух моментов времени;
7. Ввести класс для работы с объектом «полином». Реализовать следующие операции:
a. сложение (вычитание) двух полиномов;
b. умножение двух полиномов;
c. умнодение полинома на число
8. Ввести клас для работы с объектом «множество». Реализовать следующие операции:
a. объединение двух множеств;
b. пересечение двух множеств;
c. разность двух множеств;
9. Ввести клас для работы с объектом «рациональная дробь» (вида m/n). Реализовать следующие операции:
a. сложение (вычитание) двух дробей;
b. умножение (деление) двух дробей;
c. вывод дроби в виде m/n.
10. Опишите объектный тип Counter, который используется для хранения целочисленного значения счетчика и содержит методы увеличения и уменьшения его значения на единицу и на произвольное целое значение, а также получения значения счетчика.
11. Создать класс для работы с объектом символ. Реализовать операции:
a. проверка к какому алфавиту принадлежит символ;
b. изменение регистра символа;
c. нахождение кода символа
12. Опишите объектный тип AllAboutChar, который используется для хранения символьного значения и содержит методы определения, является ли заданный символ буквой, цифрой или прописной буквой.
13. Опишите объектный тип ObjString, который используется для хранения строкового значения и содержит методы проверки, является ли строка пустой, усечения строки до заданной длины и разбиения ее на две подстроки.
Лабораторная работа №7
Используя наследование, организовать доступ представителей дочернего класса к данным и методам родительского класса.
1. Родительский класс – прямоугольник со сторонами а=4 и b=5. Вычислить его периметр. Производный класс – призма высотой h=3. Вычислить ее боковую поверхность.
2. Родительский класс – ромб со стороной а=2. Вычислить его периметр. Производный класс – призма высотой h=4. Вычислить ее боковую поверхность.
3. Родительский класс – квадрат со стороной а=2. Вычислить его площадь и периметр. Производный класс – пирамида с апофемой h=4. Вычислить ее полную поверхность.
4. Родительский класс – квадрат со стороной а=5. Вычислить его периметр. Производный класс – параллелепипед высотой h=2. Вычислить его боковую поверхность.
5. Родительский класс – прямоугольный треугольник с катетами а=3 и b=4. Вычислить его площадь. Производный класс – прямая призма высотой h=7. Вычислить ее объем.
6. Родительский класс – параллелограмм со сторонами а=6 и b=8 и углом 60 градусов при основании. Вычислить его площадь. Производный класс – пирамида высотой h=3. Вычислить ее объем.
7. Родительский класс – прямоугольник со сторонами а=10 и b=7. Вычислить его площадь. Производный класс – прямоугольный параллелепипед высотой h=3. Вычислить его боковую поверхность.
8. Родительский класс – правильный шестиугольник со стороной а=8. Вычислить его периметр. Производный класс – прямая призма высотой h=4. Вычислить ее боковую поверхность.
9. Родительский класс – правильный шестиугольник со стороной а=9. Вычислить его площадь. Производный класс – пирамида высотой h=5. Вычислить ее объем.
10. Родительский класс – круг радиуса R=10. Вычислить его площадь. Производный класс – прямой конус высотой H=7 и образующей L=6. Вычислить площадь его полной поверхности.
11. Родительский класс – круг радиуса R=11. Вычислить его площадь. Производный класс – прямой конус высотой H=6. Вычислить его объем.
12. Родительский класс – правильный пятиугольник со стороной а=12. Вычислить его периметр. Производный класс – правильная пятиугольная пирамида с апофемой h=4. Вычислить ее боковую поверхность.
13. Родительский класс – правильный пятиугольник со стороной а=12. Вычислить его периметр. Производный класс – правильная пятиугольная призма с высотой h=4. Вычислить площадь ее полной поверхности.
14. Родительский класс – прямоугольник со сторонами а=14 и b=7. Вычислить его площадь. Производный класс – пирамида высотой h=3. Вычислить ее объем.
15. Родительский класс – правильный треугольник со стороной а=15. Вычислить его площадь. Производный класс –призма высотой h=6. Вычислить площадь ее полной поверхности.