Pascal. Объект (OBJECT) - Использование объектов

Идею инкапсуляции полей и алгоритмов можно применить не только к графическим объектам, но и ко всей программе в целом. Ничто не мешает нам создать объект — программу и “научить” его трем основным действиям: инициации (Init), выполнению основной работы (Run) и завершению (Done). На этапе инициации экран переводится в графический режим работы и создаются и отображаются графические объекты (100 экземпляров TPoint и по одному экземпляру TLine, TCircle, TRect). На этапе Run осуществляется сканирование клавиатуры и перемещение графических объектов. Наконец, на этапе Done экран переводится в текстовый режим и завершается работа всей программы.

Назовем объект—программу именем TGrapbApp и разместим его в модуле CraphApp (пока не обращайте внимание на точки, скрывающие содержательную часть модуля — позднее будет представлен его полный текст):

Unit GraphApp;
Interface type
TGraphApp = object
  Procedure Init;
  Procedure Run;
  Destructor Done;
end;
Implementation
Procedure TGraphApp.Init;
...
end;
end.
 

В этом случае основная программа будет предельно простой:

Program Graph_0bjects;
Uses GraphApp;
var
  App: TGraphApp;
begin
  App.Init;
  App.Run;
  App.Done
end.
 

В ней мы создаем единственный экземпляр App объекта—программы TGrahpApp и обращаемся к трем его методам.

Создание экземпляра объекта ничуть не отличается от создания экземпляра переменной любого другого типа. Просто в разделе описания переменных мы указываем имя переменной и ее тип:

var
App: TGraphApp;

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

App.Init;
App.Run;
App.Done;

Ниже приводится возможный вариант модуля GraphApp для нашей учебной программы:

Unit GraphApp;
Interface
Uses GraphObj;
const
  NPoints = 100; {Количество точек}
type
{Объект-программа}
TGraphApp = object
  Points: array [1..NPoints] of TPoint; {Массив точек}
  Line: TLine; {Линия}
  Rect: TRect; {Прямоугольник}
  Circ: TCircle; {Окружность}
  ActiveObj: Integer; {Активный объект}
  Procedure Init;
  Procedure Run;
  Procedure Done;
  Procedure ShowAll;
  Procedure MoveActiveObj(dX,dY: Integers;
end;
implementation
Uses Graph, CRT;
procedure TGraphApp.Init;
{Инициирует графический режим работы экрана. 
Создает и отображает NPoints экземпляров объекта TPoint,
 а также экземпляры объектов TLine, TCircle и TRect}
var
  D, R, Err, k: Integer;
begin
  {Инициируем графику}
  D := Detect; {Режим автоматического определения типа графического адаптера}
  InitGraph (D,R,'\tp\bgi'); {Инициируем графический режим. 
Текстовая строка должна задавать путь к каталогу с графическими драйверами}
  Err := GraphResult; {Проверяем успех инициации графики}
  if Err<>0 then
  begin
    GraphErrorMsg(Err);
    Halt;
  end;
  {Создаём точки}
  for k := 1 to NPoints do
    Points[k].Init(Random(GetMaxX),Random(GetMaxY),Random(15)+1);
  {Создаем другие объекты}
  Line.Init(GetMaxX div 3,GetMaxY div 3,2*GetMaxX div 3, 2*GetMaxY div 3, LightRed);
  Circ.Init(GetMaxX div 2,GetMaxY div 2,GetMaxY div 5,White);
  Rect.Init(2*GetMaxX div 5,2*GetMaxY div 5,3*GetMaxX div 5, 3*GetMaxY div 5, Yellow);
  ShowAll; {Показываем все графические объекты}
  ActiveObj := 1 {Первым перемещаем прямоугольник}
end; {TGraphApp.Init}
Procedure TGraphApp.Run ;
{Выбирает объект с помощью Tab и перемещает его по экрану}
var
  Stop: Boolean; {Признак нажатия Esc}
const
  D = 5; {Шаг смещения фигур}
begin
  Stop := False;
  {Цикл опроса клавиатуры}
  repeat
    case ReadKey of {Читаем код нажатой клавиши}
      #27: Stop := True; {Нажата Esc}
      #9: 
      begin {Нажата Tab}
        ActiveObj:= ActiveObj+1 ;
        if ActiveObj>3 then ActiveObj := 3
      end;
      #0: 
      case ReadKey of
        #71 MoveActiveObj(-D,-D) {Влево и вверх}
        #72 MoveActiveObj( 0,-D) {Вверх}
        #73 MoveActiveObj( D,-D) {Вправо и вверх]
        #75 MoveActiveObj(-D, 0) (Влево}
        #77 MoveActiveObj( D, 0) {Вправо}
        #79 MoveActiveObj(-D, D) {Влево и вниз]
        #80 MoveActiveObj ( О, D) (Вниз)
        #81 MoveActiveObj( D, D) (Вправо и вниз}
      end
    end
    ShowAll;
  Until Stop;
end; {TGraphApp.Run}
Destructor TGraphApp.Done;
{Закрывает графический режим}
begin
  CloseGraph;
end; {TGraphApp.Done}
Procedure TGraphApp.ShowAll;
{Показывает все графические объекты}
var
  k: Integer;
begin
  for k := 1 to NPoints do Points[k].Show;
    Line.Show;
    Rect.Show;
    Circ.Show
end;
Procedure TGraphApp.MoveActiveObj;
{Перемещает активный графический объект}
begin
  case ActiveObj of
    1: Rect.MoveTo(dX,dY);
    2: Circ.MoveTo(dX,dY);
    3: Line.MoveTo(dX,dY)
  end
end;
end.
 

В реализации объекта TGraphApp используется деструктор Done. Следует иметь в виду, что в отличие от конструктора, осуществляющего настройку ТВМ, деструктор не связан с какими-то специфичными действиями: для компилятора слова destructor и procedure - синонимы. Введение в ООП деструкторов носит, в основном, стилистическую направленность — просто процедуру, разрушающую экземпляр объекта, принято называть деструктором. В реальной практике ООП с деструкторами обычно связывают процедуры, которые не только прекращают работу с объектом, но и освобождают выделенную для него динамическую память.

В заключении следует сказать, что формалистика ООП в рамках реализации этой технологии в Турбо Паскале предельно проста и лаконична. Согласитесь, что введение лишь шести зарезервированных слов, из которых действительно необходимыми являются три (object, constructor и virtual), весьма небольшая плата за мощный инструмент создания современного программного обеспечения.