Объектно-ориентированное программирование (ООП) в Pascal — это стиль, при котором программу собирают из объектов: структур, что объединяют данные (поля) и работающие с ними подпрограммы (методы). Классы описывают, как устроен объект, а сами объекты — это конкретные экземпляры по такому описанию.
Содержание
Важная оговорка: ООП живет не в «чистом» Pascal, а в его расширении — Object Pascal. Именно на нем работают Free Pascal (компилятор fpc) и Delphi. Pascal — учебный язык, поэтому синтаксис ниже удобно проверять во Free Pascal 3.2.2 с директивой {$mode objfpc}.
Разберем: чем object отличается от class, как устроены поля и методы, конструкторы и деструкторы, инкапсуляция, наследование и полиморфизм через virtual/override.
Две разных сущности: object и class
В Object Pascal есть два ключевых слова для объектных типов, и это не синонимы:
object— старая модель из Turbo/Borland Pascal. Это значимый (value) тип: переменная хранит сам объект, обычно на стеке, память освобождается автоматически.class— современная модель из Delphi и Free Pascal. Это ссылочный (reference) тип: переменная хранит ссылку на объект в куче, который надо создать конструктором и освободить вручную.
Их легко перепутать, потому что синтаксис описания похож. Различие в модели памяти определяет почти все остальное — как создавать, удалять и передавать объекты.
| Признак | object (старый) | class (современный) |
|---|---|---|
| Происхождение | Turbo/Borland Pascal | Delphi, Free Pascal |
| Модель памяти | значимый тип, обычно на стеке | ссылочный тип, в куче |
| Создание | не требуется (или New) |
Create (конструктор) |
| Удаление | автоматически (или Dispose) |
Free вручную |
| Переменная хранит | сам объект | ссылку (nil до Create) |
| Наследование | есть | есть |
| Виртуальные методы | virtual + constructor |
virtual + override |
Свойства (property) |
ограниченно | полноценно |
| Когда брать | поддержка старого кода | новый код, GUI, Lazarus |
Далее основные примеры — на class, как в актуальном коде. Отдельно покажу object.
Поля, методы и минимальный класс
Начнем с законченного примера, который компилируется и печатает результат:
program ClassDemo;
{$mode objfpc}{$H+}
type
TCounter = class
private
FValue: Integer; // скрытое поле
public
procedure Inc;
property Value: Integer read FValue; // доступ только на чтение
end;
procedure TCounter.Inc;
begin
FValue := FValue + 1;
end;
var
c: TCounter;
begin
c := TCounter.Create; // создаем экземпляр в куче
c.Inc;
c.Inc;
WriteLn(c.Value); // 2
c.Free; // освобождаем память
end.
Здесь FValue — поле (данные), Inc — метод (подпрограмма над полями). Тело метода пишется отдельно, а его заголовок повторяет описание с префиксом-именем класса: TCounter.Inc. Внутри метода к полю обращаемся просто по имени, без указания экземпляра.
Инкапсуляция
Инкапсуляция — это объединение данных и методов в одном объекте и сокрытие внутреннего устройства за понятным интерфейсом. В примере выше FValue объявлено в секции private, поэтому снаружи его нельзя изменить напрямую — только через метод Inc и свойство Value (оно открыто лишь на чтение).
Смысл прикладной: пока класс меняет значение только своими методами, никакой чужой код не испортит его состояние случайно. Пометка про упрощение: в Free Pascal private закрывает поле на уровне модуля (внутри того же файла его видно), а строгое сокрытие на уровне класса дает strict private.
Наследование
Наследование — это создание нового класса на основе существующего: потомок получает поля и методы предка и может добавить свои. В Object Pascal предок указывается в скобках: TDog = class(TAnimal). Для обращения к реализации предка есть слово inherited.
Полиморфизм: virtual и override
Полиморфизм — это способность родственных объектов по-разному отвечать на один и тот же вызов метода. В классах он строится на паре virtual (в предке метод помечают виртуальным) и override (в потомке его перекрывают). Выбор нужной реализации происходит во время выполнения — это позднее связывание.
program Shapes;
{$mode objfpc}{$H+}
type
TShape = class
protected
FName: string;
public
constructor Create(const AName: string);
function Area: Double; virtual; // виртуальный метод
procedure Show;
end;
TCircle = class(TShape)
private
FR: Double;
public
constructor Create(AR: Double);
function Area: Double; override; // перекрываем
end;
constructor TShape.Create(const AName: string);
begin
FName := AName;
end;
function TShape.Area: Double;
begin
Result := 0;
end;
procedure TShape.Show;
begin
WriteLn(FName, ': площадь = ', Area:0:2);
end;
constructor TCircle.Create(AR: Double);
begin
inherited Create('круг'); // вызов конструктора предка
FR := AR;
end;
function TCircle.Area: Double;
begin
Result := Pi * FR * FR;
end;
var
s: TShape;
begin
s := TCircle.Create(2);
s.Show; // круг: площадь = 12.57
s.Free;
end.
Переменная s объявлена как TShape, но реально указывает на TCircle. Метод Show вызывает Area, а из-за virtual/override выполняется версия из TCircle — получаем 12.57 (площадь круга радиуса 2). Если убрать virtual и override, вызовется TShape.Area и результат станет 0.00 — это статическое связывание, полиморфизма нет.
Конструкторы и деструкторы
Конструктор (constructor Create) выделяет память под объект и инициализирует поля, деструктор (destructor Destroy) освобождает ресурсы. На практике объект уничтожают вызовом Free — он проверяет, что ссылка не nil, и вызывает Destroy. Правило простое: у каждого Create в вашем коде должен быть парный Free, иначе память утечет.
Частая ошибка новичка — использовать переменную-класс без создания объекта:
var
c: TCircle;
begin
c.Show; // c = nil, объект не создан
end.
Фактический результат при запуске:
An unhandled exception occurred at $...:
EAccessViolation: Access violation
Runtime error 216
Исправление — создать объект до обращения и освободить после:
var
c: TCircle;
begin
c := TCircle.Create(2);
c.Show;
c.Free;
end.
Старая модель: object
Тип object не требует Create/Free, если размещается на стеке. Он до сих пор компилируется во Free Pascal и встречается в старом коде:
program OldObject;
{$mode objfpc}
type
TPoint = object // значимый тип
X, Y: Integer;
procedure Init(AX, AY: Integer);
function Sum: Integer;
end;
procedure TPoint.Init(AX, AY: Integer);
begin
X := AX;
Y := AY;
end;
function TPoint.Sum: Integer;
begin
Result := X + Y;
end;
var
p: TPoint; // сам объект, на стеке
begin
p.Init(3, 4);
WriteLn(p.Sum); // 7
end.
Здесь p — это сам объект, а не ссылка. Память под него не выделяют и не освобождают вручную. Для нового кода все же берут class: у него полноценные свойства, единая модель с Delphi и Lazarus, привычные virtual/override.
Выводы
- ООП в Pascal доступно через Object Pascal (Free Pascal, Delphi), а не в «чистом» ISO Pascal.
class— ссылочный тип в куче (нужныCreateиFree);object— значимый тип на стеке (память автоматическая). Для нового кода берутclass.- Инкапсуляция закрывает поля через
privateи открывает их через методы иproperty. - Наследование задается через
class(Предок), а к предку обращаются словомinherited. - Полиморфизм работает на паре
virtualв предке иoverrideв потомке; без них вызов статический.
Где применяется / связь с практикой
Pascal остается учебным языком: на нем в школах и на первых курсах разбирают алгоритмы, структуры данных и основы ООП, а понимание классов и наследования потом переносится на Java, C# или C++. Object Pascal используют и на практике — десктопные приложения на Delphi и Lazarus строятся именно из классов.
Освойте тему на практике
Если хочется довести базу ООП до уверенной работы с алгоритмами и структурами данных, помогает системный курс с практикой и проверкой кода наставником: курс по алгоритмам и структурам данных. Оценить формат и уровень до старта можно на открытых уроках Otus — там разбирают конкретные задачи в прямом эфире.
FAQ
Чем object и class отличаются от record?
record хранит только поля (в новых версиях Object Pascal допускает и методы), но не поддерживает наследование и виртуальные методы. object и class добавляют наследование и полиморфизм.
Нужно ли вызывать Free для переменной типа object?
Нет, если object размещен на стеке — память освобождается автоматически. Ручное Free/Dispose нужно для class и для object, созданного через New.
Можно ли писать ООП в стандартном Pascal без расширений?
Нет. Классы и объекты — часть Object Pascal; во Free Pascal их включают режимы {$mode objfpc} или {$mode delphi}. В чистом ISO Pascal их нет.



