Главная страница
Навигация по странице:

  • Листинг

  • реферат Простые операторы. Характеристика форм.docx. Лр операторы и выражения Delphi


    Скачать 1.3 Mb.
    НазваниеЛр операторы и выражения Delphi
    Дата17.04.2023
    Размер1.3 Mb.
    Формат файлаdoc
    Имя файлареферат Простые операторы. Характеристика форм.docx.doc
    ТипПрограмма
    #1067638
    страница12 из 26
    1   ...   8   9   10   11   12   13   14   15   ...   26

    Управление жизненным циклом объекта


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

    • конструктор (constructor), который отвечает за создание из класса нового объекта (экземпляра класса). По существующей договоренности конструктор описывается в рамках метода Create();

    • деструктор (destructor), в обязанности которого входит уничтожение объекта. Функционал деструктора обычно закладывается в процедуру Destroy().

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


    Листинг 3.6. Объявление конструктора и деструктора класса TAutomobile




    type TAutomobile= class(TObject)

    ...

    constructor Create; //конструктор объекта

    destructor Destroy; //деструктор объекта

    end;
    constructor TAutomobile.Create; //создание автомобиля

    begin

    fEngine:=TEngine.Create; //создаем двигатель fEngine.SetEnabled(False); //в исходном состоянии двигатель выключен fSpeed:=0; //скорость автомобиля 0 км/ч

    end;
    destructor TAutomobile.Destroy; //уничтожение автомобиля

    begin

    fSpeed:=0; //автомобиль должен быть остановлен fEngine.Destroy; //уничтожаем двигатель

    end;
    В коде конструктора мы создаем двигатель автомобиля и присваиваем ссылку на него в поле fEngine. Затем мы устанавливаем параметры автомобиля в состояние по умолчанию: двигатель выключен, скорость равна 0. Во время вызова деструктора мы решаем обратную задачу — останавливаем автомобиль и уничтожаем двигатель.

    Если программист, по каким-то причинам отказался от описания конструктора и деструктора разрабатываемого класса, то создание и уничтожение объекта будет осуществлено за счет конструктора и деструктора родительского класса. В нашем примере мы не стали создавать индивидуальные методы Create() и Destroy() для двигателя TEngine. Это означает, что управление существованием двигателя будет осуществляться за счет унаследованных им методов класса-предка (в нашем случае TObject).

    Практический аспект применения конструктора и деструктора рассмотрен в листинге 3.7.


    Листинг 3.7. Создание и уничтожение объекта в коде программы




    var A : TAutomobile; //объектная переменная

    begin

    A:=TAutomobile.Create; //создаем объект

    ... //операции с объектом

    A.Destroy; //разрушаем объект

    end;

    Опережающее объявление класса


    Разрабатывая даже столь простую имитацию транспортного средства, нам все равно хочется достичь схожего поведения класса TAutomobile и реального автомобиля. Именно из-за этого, наиболее интересной частью кода стал метод SetSpeed(), управляющий скоростью машины. Благодаря программной логике, заложенной в упомянутый метод (см. листинг 5), мы не позволим набрать скорость автомобилю, если у него не включен двигатель. Предлагаю поставить перед собой еще одну задачу — при выключении двигателя скорость автомобиля должна упасть до 0.

    Если вы ненадолго вернетесь к листингу 3, в котором представлены методы класса TEngine, то вы сразу вспомните, что за остановку двигателя отвечает процедура SetEnabled() с аргументом false. На первый взгляд, может показаться, что мы находимся в одном шаге от решения поставленной задачи — надо лишь дополнить метод SetEnabled() строкой кода

    if Value=false then fAutomobile.fSpeed:=0;

    Однако на практике это невозможно. Причина проста — класс TEngine не имеет ни малейшего представления даже о существовании класса TAutomobile, не говоря уже о его полях и методах. Поэтому упоминание поля автомобиля fSpeed в методе двигателя приведет к одному — Delphi скажет, что идентификатор не объявлен (undeclared identifier) и откажется компилировать проект.

    Какой выход из создавшегося положения? Ответ таков: надо сделать так, чтобы двигатель знал, в какую машину он установлен. Для этого я введу в состав класса TEngine еще одно поле — fAutomobile:TAutomobile. Однако в нашем листинге класс TAutomobile объявлен после класса TEngine, поэтому двигатель по-прежнему не понимает, что такое TAutomobile. Для устранения этой проблемы воспользуемся еще одной хитростью Delphi — опережающим объявлениемкласса.

    Суть идеи опережающего объявления заключается в том, что мы заявим о намерении описать класс TAutomobile практически в первых строках листинга, а реальное описание оставим на прежнем месте (после описания двигателя). Благодаря такой уловке класс TEngine перестанет отвергать поле fAutomobile.

    Листинг 3.8 содержит усовершенствованное объявление классов TEngine и TAutomobile.


    Листинг 3.8. Улучшенный способ объявления классов TEngine и TAutomobile



    {начало объявлений, одно ключевое слово type для TEngine и TAutomobile}

    type

    TAutomobile=class; //опережающее объявление класса TAutomobile
    {полное объявление класса TEngine}

    TEngine=class fEnabled :boolean;

    fAutomobile :TAutomobile; //автомобиль, в который установлен двигатель

    //другие поля и методы класса

    end;
    {полное объявление класса TAutomobile} TAutomobile=class(TObject)

    fSpeed:single; //скорость движения

    //другие поля и методы класса

    end;

    Обязательно обратите внимание на небольшое изменение в порядке объявления классов. Раньше (см. листинги 3.2 и 3.3) описание каждого из классов начиналось с отдельного ключевого слова type, в новой версии кода для обеспечения видимости опережающего объявления класса TAutomobile мы ограничились одним словом type.

    Еще одна синтаксическая особенность опережающего объявления в том, что заявление о существовании класса заканчивается не ключевым словом end, как того требует синтаксис (листинг 1). Вместо этого точка с запятой ставится сразу после инструкции class.

    Добившись того, что класс TEngine узнал о существовании класса TAutomobile, усовершенствуем конструктор автомобиля (листинг 3.9).


    Листинг 3.9. Исправление конструктора класса TAutomobile




    constructor TAutomobile.Create;

    begin

    fEngine:=TEngine.Create; //создаем двигатель fEngine.fAutomobile:=self; //двигатель получил ссылку на автомобиль fEngine.SetEnabled(False); //исходное состояние двигатель выключен

    end;
    Теперь, в момент создания автомобиля, ссылка на экземпляр класса TAutomobile будет передана в соответствующее поле экземпляра класса TEngine. Благодаря ссылке двигатель получает возможность обращаться к полям и методам автомобиля.

    Нам осталось сделать последний штрих дополнить метод включения/отключения двигателя

    SetEnabled() командой на остановку автомобиля (листинг 3.10).


    Листинг 3.10. Остановка автомобиля в момент выключения двигателя




    procedure TEngine.SetEnabled(Value: Boolean);

    begin

    fEnabled:=Value;

    if Value=false then

    if Assigned(fAutomobile) then {если есть связанный объект} fAutomobile.fSpeed:=0;

    end;

    1   ...   8   9   10   11   12   13   14   15   ...   26


    написать администратору сайта