реферат Простые операторы. Характеристика форм.docx. Лр операторы и выражения Delphi
Скачать 1.3 Mb.
|
Управление жизненным циклом объектаЛюбой класс автоматически вооружается парой специализированных методов, несущих прямую ответственность за жизненный цикл объекта. Это: конструктор (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; |