Создание и разрушение объекта

Введение в объектно-ориентированное программирование

Язык программирования Object Pascal и его достойный преемник, среда программирования Delphi, построены на основе получившей широкое развитие на стыке 70–80-х годов XX века теории объектно-ориентированного программирования (Object-Oriented Programming, OOP). В то время идея описания программ в базисе логических сущностей и взаимодействия между ними не была такой уж бесспорной, а у некоторых оппонентов даже вызывала определенное недоумение.

Пока консервативно настроенные личности занимались критикой новой идеи и всячески пропагандировали традиционный по тем временам процедурный стиль, компания Borland и корпорация Microsoft активно занялись разработкой концептуально новых систем программирования. Спустя сравнительно небольшой промежуток времени на рынке появились среды разработки ПО, совершившие революционный переворот в самой идее программирования. В первую очередь это объектно-ориентированные C++ и Object Pascal, а чуть позднее Microsoft Visual C++, Borland C++ Builder и, конечно же, Borland Delphi.

Появление даже первых версий этих систем поумерило пыл критиков ООП. Трудно придираться к программным продуктам, в которых создание классического примера «Hello, World» занимает не более минуты и обходится без единой строки кода. Для сравнения аналогичная задача на старом добром языке С потребует не менее 50 строк кода.

Подчеркну, что материал этой главы не претендует на «всеобъемлющее изложение концепции объектно-ориентированного программирования». Задача скорее обратная – познакомить читателя с основными понятиями ООП и провести вступительную экскурсию по объектам и классам, дабы подготовить новичков к изучению среды программирования Delphi. Более углубленная версия предлагается в главе 16 «Создание компонентов».

 

Объект и класс

Уже само название концепции «объектно-ориентированное программирование» указывает на то, что ключевой фигурой в OOП является объект. Что же это такое? В окружающей нас среде объект – это то, что можно пощупатьруками, это книга, кнопка на клавиатуре, сама клавиатура, настольная лампа, проезжающий за окном автомобиль. Каждый объект обладает некоторыми характеристиками, сравнивая которые мы можем судить о сходстве или различии объектов. Так, несмотря на схожесть кнопок клавиатуры, мы различаем их по сопоставленному им символу алфавита. Кроме того, есть характеристики, взглянув на которые мы можем судить о текущем состоянии объекта, например, лампа включена или выключена, автомобиль мчится со скоростью 60 км/ч.

Все присущие объекту характеристики в терминах OOП называют полями. По сути, это принадлежащие объекту переменные определенного типа, в которые записываются значения, отражающие состояние объекта. Для управления объектом предназначены его методы. Настольной лампой управляют два ключевых метода: включить и выключить. У автомобиля этих методов значительно больше: он заводится, набирает скорость, изменяет направление движения, замедляет движение и все это время пожирает бензин. В первую очередь методы воздействуют на поля объекта. Так, практически все методы автомобиля сосредоточены вокруг поля, описывающего его скорость. Если методы объекта возвращают какое-нибудь значение, то они реализуются в виде функции, в противном случае метод представляется процедурой.

Объект не может возникнуть из воздуха, среда программирования каким-то образом должна быть проинформирована о его характеристиках. Поэтому предварительно программист описывает объект; такое описание называется классом. Класс – это чертеж будущего объекта, в котором учитываются не только его конструктивные элементы (поля), но и определяются способы управления этими элементами – методы класса.

Определение класса начинается с ключевого слова type, за которым следуют имя класса, его поля и методы. Завершается описание директивой end. Например, объявление класса простейшего автомобиля могло бы выглядеть примерно так:

 

Type

TAutomobile = class

fSpeed : smallint;

procedureSetSpeed(Value : SmallInt);

end;

 

Созданный на основе класса объект способен только изменять скорость – содержимое поля fSpeed.

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

 

Type

TEngine = class//класс двигатель

fOn : Boolean; //поле вкл/выкл

procedureEngineOn; //включить двигатель

procedureEngineOff; //выключить двигатель

end;

Двигатель TEngine умеет запускаться и останавливаться, для чего реализованы соответствующие методы. О текущем состоянии двигателя можно судить по полю fOn.

 

Type

TAutomobile = class

fSpeed : smallint;

fEngine : TEngine; //интеграция класса TEngine в состав класса TAutomobile

procedureSetSpeed(Value : SmallInt);

end;

 

Двигатель интегрируется в состав общего класса автомобиля в виде отдельного поля. Для обращения к полю или методам вложенного класса необходимо лишь указать его принадлежность. Например, для того чтобы завести автомобиль, потребуется следующая строка кода:

 

varAutomobile : TAutomobile;

Automobile.fEngine.EngineOn;

 

Скажете, это все теория. Хорошо, взглянем на классы и объекты с практической стороны. При разработке обычного приложения с объявлением классов и созданием объектов Delphi справляется без посторонней помощи. Чтобы убедиться в этом, запустите среду программирования. По умолчанию создается новый проект с одной-единственной формой. Заглянув в редактор кода, вы увидите следующие строки:

 

unitUnit1;

Interface

Uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs;

Type

TForm1 = class(TForm)

Private

{ Private declarations }

Public

{ Public declarations }

end;

varForm1: TForm1;

Implementation

{$R *.dfm}

end.

 

Пока наш проект практически пуст. В нем объявлен единственный класс формы TForm1, а в разделе переменных объявлена переменная объектного типа Form1: TForm1. После старта приложения и создания экземпляра класса TForm1 в этой переменной будет храниться ссылка на объект. А теперь разместите на поверхности формы любой из компонентов, например строку ввода (элемент управления TEdit со страницы Standard, рис. 5.1). После этого вернитесь в редактор кода. В теле объявления класса TForm1 появилось одно очень важное изменение – новый объект Edit1, создаваемый из класса TEdit.

Type

TForm1 = class(TForm)

Edit1: TEdit;

Private

{ Private declarations }

Public

{ Public declarations }

end;

 

Отметим одну важную особенность, касающуюся обращения к объекту. Если нам потребуется обратиться к строке ввода Edit1 из этого же модуля Unit1, то достаточно просто указать имя вызываемого компонента:

Edit1.Text:= 'Hello World!';

Однако приложения очень часто состоят из двух и более форм. И если вы попытаетесь из другой формы изменить текст в строке ввода формы Form1 предложенным выше способом, то компилятор сообщит, что он не знает о существовании компонента с именем Edit1.

При обращении к компоненту, принадлежащему другой форме, сначала надо сослаться на форму, владеющую этим компонентом:

Form1.Edit1.Text:= 'Hello World!';

Это правило также относится к вызову всех опубликованных (описанных в секции

public) полей и методов другой формы.

Создание и разрушение объекта

Все размещаемые на поверхности формы компоненты создаются и уничтожаются автоматически. В простейших приложениях программисту, как правило, даже нет необходимости вмешиваться в их жизненный цикл. Но если вы собираетесь создавать профессиональные программные продукты, то безусловно стоит узнать, как рождается и умирает объект.

Любой класс снабжен двумя специализированными методами: конструктором (constructor) и деструктором (destructor). Конструктор предназначен для создания экземпляра класса; в результате его вызова рождается новый объект и инициализируются его поля. Обычно конструктор реализуется в виде функции Create(). Деструктор – это антипод конструктора; его задача кардинально противоположная – уничтожить объект и освободить отведенные под него системные ресурсы. По существующей традиции деструктор реализуется в виде процедуры Destroy().

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

Type

TAutomobile = class

constructorCreate;

destructorDestroy;

end;

 

Пусть вас не вводит в недоумение несколько нетрадиционный синтаксис объявления этих методов. В данном случае нет необходимости применять привычные ключевые слова procedureи function, а также не надо указывать тип возвращаемого функцией Create() значения, т. к. компилятор и без нашей помощи знает, что конструктор создает экземпляр класса TAutomobile. На практике применение конструктора и деструктора не вызывает особых затруднений:

 

varAutomobile : TAutomobile;

Begin

Automobile:= TAutomobile.Create;

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

Automobile.Destroy;

end;

 

Программист объявляет переменную объектного типа, конструирует этот объект, проводит с ним запланированные операции и затем уничтожает его. Зачастую обязанности по созданию и уничтожению объектов берет на себя Delphi. Например, при разработке приложения средней сложности среда программирования в состоянии взять на себя полную ответственность за создание формы и принадлежащих ей компонентов. Но если программист намерен создавать объекты самостоятельно, то он должен помнить правило: все созданное нашими руками по окончании работы должно быть уничтожено нами же. В этом случае не принято полагаться на сообразительность любой среды разработки, в том числе и Delphi.

Функция Create() относится к группе так называемых методов класса (class functions).

Это особая категория методов, которые могут вызываться не от имени

объекта, а от имени его класса.

Операторы класса

В Delphi предусмотрено два специализированных оператора, называемых операторами класса: isи as. Оператор isпредназначен для проверки принадлежности объекта к определенному классу:

 

if(MyObject isTComponent)=True then

 

Ключевая особенность оператора isв том, что он проверяет не только непосредственного предка объекта, а всю иерархическую цепочку наследования объекта в целом. И если TComponent будет предком объекта MyObject даже в десятом колене, то конструкция вернет true.

Оператор asназывается оператором приведения типа. Это очень грозное и притом опасное оружие, поэтому использование оператора asдолжно быть максимально продуманным.

 

with(MyObject asTControl) do

 

Оператор приведения типа позволяет явным образом указывать Delphi, что объект MyObject должен действовать как экземпляр класса TControl. И горе той программе, которая с помощью оператора asпопробует заставить объект выполнить несвойственные ему действия. Такая попытка в лучшем случае закончится вызовом исключительной ситуации. Поэтому сразу приведу пример безопасного приведения типов:

 

vari : integer;

Begin

fori:=0 toForm1.ComponentCount-1 do








Дата добавления: 2016-03-15; просмотров: 1040;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.028 сек.