Элементы ООП

Понятие объекта и его применение


Объект в Турбо Паскале – это структура данных, содержащая поля данных различных типов и заголовки методов. Метод – процедура или функция объекта.

Для описания объекта используется зарезервированное слово object:

                        

Type MyObj = object {объект - родитель}
поле1;
поле n;
метод1;
метод k;
end;

MyObj2= object (MyObj) {объект – потомок от MyObj}
{поля};
{методы};
end;

Директива Private в описании объекта открывает секцию скрытых полей и методов. Перечисленные в этой секции элементы объекта «не видны» программисту, если этот объект он получил в рамках библиотечного tpu - модуля. Скрытые поля доступны в модуле, где описан объект.
Директива Public отменяет действие директивы Private, поэтому все следующие за Public элементы доступны в любой программной единице. Директивы Private и Public могут произвольным образом чередоваться в пределах одного объекта.
Для описания методов в ООП используются традиционные для Паскаля процедуры и функции, а так же особый вид процедур – конструкторы и деструкторы.
Конструкторы предназначены для создания конкретного экземпляра объекта, ведь объект – это тип данных, т.е. «шаблон», по которому можно создавать сколько угодно рабочих экземпляров данных объектного типа. Типичное действие, реализуемое конструктором, состоит в наполнении объектных полей конкретными значениями. Зарезервированное слово Constructor используется вместо Procedure. Если в объекте есть хотя бы один метод, описанный как виртуальный (Vitrual – виртуальный, воображаемый. См. метод Draw– вычерчивание графического объекта), в состав объекта должен входить хотя бы один конструктор и обращение к конструктору должно предшествовать обращению к любому виртуальному методу.
Деструктор Dectructor синоним Procedure. Введение в ООП деструкторов носит в основном стилистическую направленность – просто процедуру, разрушающую экземпляр объекта принято называть деструктором.

Учебная задача

Разработать программу, которая создает на экране ряд графических изображений (точки – случайным образом, линия, окружность, прямоугольник) и может перемещать эти изображения по экрану.

Tab – выбор перемещаемого объекта
Esc – выход из программы
Перемещение с помощью стрелок: вверх, вниз, влево, вправо
  1. Создадим объект – родитель (GObj), в котором будут включены поля и методы общие для всех остальных объектов. Это будет абстрактный объект – не связан с конкретной графической фигурой. Каждая из графических фигур характеризуется положением на экране (поля Х и У) и цветом (поле Color). Общие методы: Конструктор Init – получает все необходимые данные для полного определения экземпляра объекта (через параметры обращения aX, aY, aColor)
    Draw – отображение объекта на экране. Виртуальный метод, т.к. каждый объект – потомок будет по-своему отображать себя на экране.
    Show – «показать себя»
    Hide – «спрятать себя»
    Moveto – перемещение по экрану
  2. Затем создадим объекты - потомки от GObj, реализующие все специфические свойства точки, линии, (окружности и прямоугольника – самостоятельно)
  3. Описание объектов поместим в модуль u_Gobj.tpu

    ПРОГРАММА

    Модуль U_Gobj
    unit u_gobj;
    interface
    type
    gobj=object {объект - родитель}
    {private}
    x,y:integer; {поля}
    color:word;
    {public}
    constructor init (ax,ay:integer; acolor:word); {методы объекта}
    procedure draw(acolor:word); virtual;
    procedure show;
    procedure hide;
    procedure moveto(dx,dy:integer);
    end;

    {объект – точка. Основные действия наследует, следовательно в объекте перекрывается единственный метод Draw}

    tpoint=object(gobj)
    procedure draw(acolor:word); virtual;
    end;

    {объект – линия. Два новых поля – координаты второго конца. Дополнительные поля требуется наполнить конкретными значениями, следовательно перекрывается конструктор объекта – родителя и метод Draw}

    tline=object(gobj)
    dx,dy:integer;
    constructor init (x1,y1,x2,y2:integer; acolor:word);
    procedure draw(acolor:word); virtual;
    end;

    implementation {описание всех методов}
    uses graph;

    constructor gobj.init;
    begin
    x:=ax;
    y:=ay;
    color:=acolor;
    end;

    procedure gobj.draw;
    begin
    end;

    procedure gobj.show;
    begin
    draw(color);
    end;

    procedure gobj.hide;
    begin
    draw(getbkcolor);
    end;

    procedure gobj.moveto;
    begin
    hide;
    x:=x+dx;
    y:=y+dy;
    show;
    end;

    procedure tpoint.draw;
    begin
    putpixel(x,y,acolor);
    end;

    constructor tline.init;
    begin
    Gobj. init(x1,y1,acolor);
    dx:=x2-x1;
    dy:=y2-y1;
    end;

    procedure tline.draw;
    begin
    setcolor(acolor);
    line(x,y,x+dx,y+dy);
    end;

    end.

    Использование объектов

    Идею инкапсуляции полей и алгоритмов можно применять не только к графическим объектам, но и ко всей программе в целом.

    Объект – программа (три основных действия):

    1. Init – инициализация. Экран переводится в графический режим работы и отображаются объекты (100 экземпляров Tpoint, по одному экземпляру Tline и др.)
    2. Run – выполнение основной программы. Осуществляется сканирование клавиатуры и перемещение графических объектов
    3. Done – завершение. Экран переводится в текстовый режим и завершается работа всей программы.

    Gapp – имя объекта – программы, который поместим в модуль u_Gapp.tpu (см. ниже)

    Основная программа будет простой:

    program gr_object;
    uses u_gapp;
    var app:gapp;
    begin
    app.init;
    app.run;
    app.done
    end.

    Вариант модуля u_Gapp.tpu для нашей учебной задачи:

    unit u_gapp;
    interface
    uses u_gobj;
    const npoints=100; {количество точек}
    type gapp=object
    points:array[1..npoints] of tpoint;
    {массив точек}
    line:tline;{линия}
    actobj:integer; {активный объект}
    procedure init;
    procedure run;
    procedure done;
    procedure showall; {показывает все графические объекты}
    procedure moveactobj(dx,dy:integer);
    {перемещает активный графический объект}
    end;

    implementation
    uses graph, crt;

    procedure gapp.init;
    var gd,gm,k: integer;
    begin
    gd:=detect;
    initgraph(gd,gm,'');
    {инициализация 100 точек}
    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,red);
    showall;
    actobj:=1; {первой перемещаем линию}
    end;

    procedure gapp.run;
    var stop: boolean; {признак нажатия Esc}
    const d=5; {шаг смещения}
    begin
    stop:=false;
    repeat {цикл опроса клавиатуры}
    case readkey of
    #27: stop:=true;
    #9: begin
    inc(actobj);
    if actobj>2 then actobj:=1
    end;
    #0: case readkey of
    #72: moveactobj(0,-d); {вверх}
    #75: moveactobj(-d,0); {влево}
    #77: moveactobj(d,0); {вправо}
    #80: moveactobj(0,d); {вниз}
    end;end;
    showall;
    until stop;
    end;

    procedure gapp.done;
    begin
    closegraph;
    end;

    procedure gapp.showall;
    var k: integer;
    begin
    for k:=1 to npoints do
    points[k].show;
    line.show;
    end;

    procedure gapp.moveactobj;
    begin
    case actobj of
    1: line. moveto (dx,dy);
    2: for k:=1 to npoints do points[k]. moveto (dx,dy);
    end;
    end;
    end.



    Назад