Рефераты. Программирование на Delphi

В Delphi 4 в класс tObject добавлены еще два виртуальных метода - AfterConstruction и BeforeDestruction. Как следует из названия, они вызываются сразу после создания экземпляра объекта и непосредственно перед уничтожением.

Перегрузка методов

В Delphi 4 появилась новая разновидность методов - перегружаемые. Перегрузка нужна для того, чтобы произвести одинаковые или похожие действия над разнотипными данными. Перегружаемые методы описываются с ключевым словом overload.

Type
tFirstClass=class
E:extended;
procedure SetData(aValue: Extended); overload;
end;

tSecondClass=class(tFirstClass)
I:integer;
procedure SetData(aValue: Integer); overload;
end;

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

Для перегрузки виртуального метода используется зарезервированное слово reintroduce:

procedure SetData(aValue:string); reintrouce;overload;

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

Абстрактные методы

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

Procedure NeverCallMe; virtual; abstract;

Никакого кода абстрактный метод не содержит. Его вызов приведет к созданию исключительной ситуации eAbstractError.

События

Операционная система Windows® основана на сообщениях. Сообщения эти возникают в результате действий пользователя, аппаратуры компьютера или других программ. Таких сообщений в Windows сотни, и по большому счету, написать программу для Windows - значит определить реакцию на некоторые из них.

Работать с таким количеством сообщений, даже имея под рукой справочник, нелегко. Поэтому одним из главных преимуществ Delphi является то, что программист полностью избавлен от необходимости работать с сообщениями Windows (хотя такая возможность у него имеется). Типовых событий в Delphi - не более двух десятков, и все они имеют простую интерпретацию, не требующую глубоких знаний среды.

С точки зрения языка, событие - это поле процедурного типа, предназначенное для создания пользовательской реакции на те или иные входные воздействия:

Property OnMyEvent: tMyEvent read FMyEvent write FMyEvent;

Здесь OnMyEvent - поле объекта, содержащее адрес некоторого метода. Присвоить такому свойству значение - значит указать программе адрес метода, который будет вызываться в момент наступления события. Такие методы называются обработчиками событий.

Внутри библиотеки времени выполнения Delphi вызовы обработчиков событий находятся внутри методов, обрабатывающих сообщения Windows. Выполнив необходимые действия, этот метод проверяет, известен ли адрес обработчика, и, если это так, вызывает его.

События имеют разное количество и тип параметров, в зависимости от происхождения и назначения. Общим для всех события является параметр Sender - он указывает на объект, вызвавший событие. Самое простое событие - tNotifyEvent - не имеет других параметров.

tNotifyEvent = procedure(Sender:tObject) of object;

Тип метода, предназначенный для извещения о нажатии клавиши, предусматривает передачу в процедуру кода этой клавиши, о передвижении мыши - ее текущих координат и т.д.

Имя события в Delphi начинается с префикса On: OnClick, OnCreate, OnMouseDown и т.д. Имена методов - обработчиков событий состоят из имени объекта, генерирующего событие, и корня имени события: OkButtonClick. Дважды щелкнув мышью в инспекторе объектов на странице Events в поле напротив любого события, вы получите скелетный код (заготовку) этого события.

Поскольку события - это свойства объекта, их значения можно менять в любой момент во время выполнения программы. Эта возможность называется делегированием. Можно в любой момент взять способы реакции на события у одного объекта и присвоить (делегировать) их другому.

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

Один и тот же обработчик может обрабатывать события от разных объектов. Типичный пример - в современных программах одно и то же действие можно вызвать несколькими способами - через главное меню, контекстное меню и т. д. Этого легко добиться, назначив один и тот же обработчик всем необходимым объектам в инспекторе объектов. азумеется, события должны быть одного и того же типа.

Более сложный случай - когда внутри обработчика необходимо определить, какой именно объект вызвал событие. Если объекты, которые потенциально могут это сделать, имеют разный тип, то именно их тип можно применить в качестве критерия:

If Sender is tMenuItem then ...

Если же все объекты, разделяющее между собой один обработчик события, относятся к одному классу, можно использовать свойство tObject.Tag.

Ниже приведены названия некоторых, наиболее употребительных событий Delphi:

Событие - Тип обработчика - Когда возникает

OnClick - TNotifyEvent - При нажатии левой клавиши мыши

OnActivate - TnotifyEvent - После передачи объекту фокуса

OnCreate - TnotifyEvent - После создание объекта

OnDestroy - TnotifyEvent - Перед уничтожением объекта

OnDeactivate - TnotifyEvent - Перед уходом фокуса из объекта

OnKeyPress - TkeyPressEvent - При нажатии клавиши

OnMouseDown - TmouseEvent - При нажатии клавиши мыши

OnMouseMove - TmouseMoveEvent - При движении мыши над объектом

OnMouseUp - TmouseEvent - При отпускании клавиши мыши

а также их типы:

Тип
Описание

TnotifyEvent
type TnotifyEvent = procedure (Sender: TObject) of object;

TkeyPressEvent
type TkeyPressEvent = procedure (Sender: TObject; var Key: Char) of object;

TmouseEvent
TmouseEvent = procedure (Sender: TObject; Button: TmouseButton; Shift: TShiftState; X, Y: Integer) of object;

TmouseMoveEvent
TmouseMoveEvent = procedure(Sender: TObject; Shift: TShiftState; X, Y: Integer) of object;

Стандартные события описаны в модуле Classes.

Динамические массивы

В Delphi существуют динамические массивы, то есть массивы, длину которых можно изменять во время выполнения программы. аньше проблема динамических массивов стояла довольно остро. Стандартных средств для работы с ними не было, и программистам приходилось вручную создавать подобные структуры (как правило, на основе динамических переменных). Теперь компилятор Delphi сам выполняет всю “грязную” работу. Параллельно с динамическими, в Delphi сохранились и обычные, статические массивы.

Длина динамических массивов определяется уже во время выполнения программы. Описав переменную как

var A1:array of real,

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

procedure SetLength(var A; NewLength: Integer);

Здесь A - указатель на динамический массив, NewLength - длина массива.

В динамических массивах нумерация индексов начинается только с нуля.

То обстоятельство, что динамические массивы фактически являются указателями, приводит к определенным нюансам в их использовании. Первый из них касается присвоения массивов. Запись

Var A1,A2:array[0..4] of real;
A1:=A2;

В случае со статическими массивами, означает, что всем элементам массива A1 присваиваются значения соответствующих элементов массива A2, но при этом, переменные A1и A2 - разные переменные, хранящиеся в разных областях памяти.

В случае с динамическими массивами присвоение их друг другу - не более чем присвоение указателей. ассмотрим пример:

Var A1,A2:array of real;
. . .
SetLength(A1,5);
A1[0]:=0.0;
A2:=A1;
A2[0]:=2.0;

Значение A2[0] также изменится и станет равно 2. Это произошло потому, что после присвоения указатели ссылаются на один и тот же адрес в памяти и изменения в одном массиве приведут к синхронным изменениям в другом.

Для того, чтобы действительно скопировать элементы в A2, необходимо использовать функцию Copy:

function Copy(A; Index, Count: Integer): string;

Здесь А - указатель на копируемый массив,

Index - индекс первого копируемого элемента,

Count - число копируемых элементов.

A2:=Copy(A1,0,Length(A1));

Освободить выделенную под массив память можно при помощи процедуры finalize:

procedure Finalize( var A [; Count: Integer] );

здесь V - указатель на динамический массив, Count - количество массивов (в случае, когда несколько динамически создаваемых структур размещаются подряд в одном непрерывном блоке памяти, их можно освободить одним вызовом Finalize); или просто присвоив указателю на массив значение nil. В этом случае память не будет потеряна (как могло бы показаться на первый взгляд), а будет вызвана соответствующая процедура, корректно освобождающая память. Причем, память освободиться только тогда, когда на нее не уже не ссылается ни одна динамически созданная структура.

Значения граничных индексов (как статических так и динамических) можно получить при помощи функций Low(A) - нижний граничный индекс и Hight(A) - верхний граничный индекс. Число элементов массива - функцией Length:

function Length(A): Integer;

Дальнейшим развитием идеи динамических массивов являются многомерные динамические массивы.

Var AA: array of arrray of real;
SetLength(AA,10,5);
AA[9,4]:=1;
AA[9][4]:=1;

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

SetLength(AA,10);

Страницы: 1, 2, 3, 4, 5, 6, 7, 8



2012 © Все права защищены
При использовании материалов активная ссылка на источник обязательна.