Делегируемое свойство должно возвращать объект, чей класс полностью реализует интерфейс, без использования выражений различия методов (“мэппинга”), см. далее. Например:

type

IMyInterface =

interface

procedure P1;

procedure P2;

end;

TMyClass =

class(TObject, IMyInterface)

FMyInterface: IMyInterface;

property MyInterface: IMyInterface

read FMyInterface

implements IMyInterface;

end;

tatherClass=

class(tany, ImyInterface)

end;

var

aMyClass: TMyClass;

aOtherClass:tOtherClass;

aMyInterface: IMyInterface;

begin

aMyClass := TMyClass. Create;

aMyClass. FMyInterface := ... // объект, чей класс реализует ImyInterface

aMyInterfase:=aMyClass. myInterfase// ссылка на тот же объект

aMyInterface := MyClass;// допустимо, так как ImyInteface – интерфейс-прародитель для tMyClass; ссылка на объект, агрегирующий

aMyInterface. MyInterface:=totherClass. create;//это второй объект

aMyInterface. P1;

aMyInterfase. MyInterfase. P1;//это вызов методаP1 для второго объекта

end;

6.3. Различение имен при реализации нескольких интерфейсов

Когда класс реализует два или более интерфейсов, имеющих методы с одинаковыми именами, для разрешения конфликта имен используют выражения различения методов в виде “мэппинга”:

procedure interface. interfaceMethod = implementingMethod;

или

function interface. interfaceMethod = implementingMethod;

где implementingMethod — это метод, определенный в классе, или одном из его прародителей. Он может быть методом, описанном далее в описании класса, но не может быть “private” методом класса или одного из его прародителей, описанном в другом модуле. Пример:

НЕ нашли? Не то? Что вы ищете?

type

TMemoryManager = class(TInterfacedObject, IMalloc, IErrorInfo)

function IMalloc. Alloc = Allocate;

procedure IMalloc. Free = Deallocate;

...

end;

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

В спецификации интерфейса может быть описан уникальный глобальный идентификатор — globally unique identifier (GUID), представленный в виде строки литералов, заключенной в скобки:

['{xxxxxxxx–xxxx–xxxx–xxxx–xxxxxxxxxxxx}']

где каждый X это 16-ричная цифра ( от 0 до F). GUID — это 16-байтовое двоичное число, уникально идентифицирующее интерфейс.

Если у интерфейса есть GUID, можно его использовать для запросов к переменной интерфейса, получить ссылки на его реализации. Типы tGUID и pGUID, определенные в модуле System, используются для работы с переменными типа GUID и указателями на такие переменные. Их описание следующее:

type

pGUID = ^tGUID;

tGUID =

record

D1: Longword;

D2: Word;

D3: Word;

D4: array[0..7] of Byte;

end;

Можно описать типизированную константу типа TGUID, например, имеющую имя IID - IMalloc:

const IID_IMalloc: TGUID = '{00000002-0000-0000-C000-000000000046}';

Вызов в процедуре переменной типа GUID аналогичен соответствующему типу interfase. Может быть использовано как значение, так и постоянный параметр типа TGUID. Например:

function Supports(Unknown: IUnknown; const IID: TGUID): Boolean;

Таким образом, вызов Supports может быть сделан одним из двух путей:

if Supports(Allocator, IMalloc) then...

или

if Supports(Allocator, IID_IMalloc) then...

5.11. Спецификаторы вызовов процедур и функций

При задании процедуры или функции можно использовать спецификаторы вызова register, pascal, cdecl, stdcall, safecall. Например:

function MyFunction(X, Y: Real): Real; cdecl;

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

Директива

Передача параметров

Очищает стек

Передает параметры

Вызовы

Register

слева направо

программа

через регистры

по умолчанию, наиболее эфф.

Pascal

слева направо

программа

через стек

обратно совместимо с Turbo PASCAL

cdecl

справа налево

вызывающий

через стек

DLL, написанные на C или C++

stdcall

справа налево

программа

через стек

Windows API

safecall

справа налево

программа

через стек

Объекты COM; методы парных интерфейсов

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

Было:

var

A: array[1..100] of string;

B: array[1..10] of array [1..20] of integer;

Стало можно:

var

A: array of string;

B: array of array of integer;

Декларация динамического массива (переменных A и B) не выделяет под них памяти. Память выделяется процедурой SetLength:

SetLength(A,100);

SetLength(B,10,20);

Индексация динамических массивов всегда идет от нуля.

Для освобождения памяти из-под динамического массива:

а) либо присвоить nil переменной:

A:=nil;

B:=nil;

б) либо — вызвать процедуру Finalize:

Finalize(A);

Finalize(B);

Пример:

unit Unit1;

interface

uses

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

StdCtrls;

type

TForm1 = class(TForm)

Button1: TButton;

Button2: TButton;

Label1: TLabel;

Label2: TLabel;

Button3: TButton;

Label3: TLabel;

Label4: TLabel;

Label5: TLabel;

Button4: TButton;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure Button3Click(Sender: TObject);

procedure Button4Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

A: array of string;

B: array of array of integer;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);

begin

close

end;

procedure TForm1.Button2Click(Sender: TObject);

begin

SetLength(A,100);

SetLength(B,10,20);

Label1.caption:='Память выделена';

end;

procedure TForm1.Button3Click(Sender: TObject);

var s:string;

begin

A[99]:='Ok';

B[9,19]:=7;

Label3.caption:=A[99];

str(B[9,19],s);

Label5.caption:=s;

end;

procedure TForm1.Button4Click(Sender: TObject);

begin

A:=nil;

Finalize(B);

Label1.caption:='Память освобождена';

end;

end.

5.13. Перезагрузка (overloading) методов, процедур и функций

Разрешено использование одинаковых имен, но с разными сигнатурами аргументов (числом или типом аргументов):

Constructor create(aOwner:tComponent);overload;override;

Constructor create(aOwner:tComponent;Text:String);overload;

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

Constructor create(aOwner:tComponent;Name:String);overload;

Пример для функций:

function Divide(x, y:real):Real;overload;

begin

Result:=x/y;

end;

function Divide(x, y:integer):Integer;overload;

begin

Result:=x div y;

end;

5.14. Параметры по умолчанию

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

Name: Type=value;

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

Procedure FillArray(A:array of integer;V:integer=1);

Тогда вызов этой процедуры можно производить так:

FillArray(myArray,1);

Либо, что то же,

FillArray(myArray);

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

Технология Drag and Drop

Особенности разработки DLL

Работа программ с DLL (Dynamic Link Library) поддерживается операционной системой, а не компилятором какого-либо языка программирования. Они представляют собой универсальный механизм использования в программах библиотек - набора процедур и функций. Разные DLL могут быть написаны на различных языках программирования, что обычно не мешает их использованию в программах, написанных на другом языке программирования.

DLL не в состоянии поставлять в программу переменные, константы и типы. В результате DLL не могут экспортировать в программу объекты – для этого в Object PASCAL используются пакеты. DLL подключаются к программе в момент ее исполнения, т. е. динамически. Значительным преимуществом DLL является то, что если несколько программ используют одну и ту же DLL, в памяти будет лишь один экземпляр разделяемого программами кода. При необходимости DLL могут динамически загружаться и выгружаться из памяти программным путем.

Для создания DLL в Object Pascal введено зарезервированное слово Library, которым должен начинаться текст библиотеки. За словом Library следует ее идентификатор, но в отличие от модуля работа с DLL определяется именем DLL-файла, а не идентификатором, следующим за Library.

Структура текста DLL повторяет структуру обычной программы с тем исключением, что операторы блока реализации в DLL исполняются только один раз в момент загрузки библиотеки в память. Каждое очередное обращение с требованием загрузить библиотеку наращивает на единицу счетчик ссылок, но не приводит к выполнению операторов исполняемой части, что экономит ресурсы компьютера.

Сразу за заголовком списываемой в библиотеке экспортируемой процедуры или функции должно следовать зарезервированное слово Export, которое позволяет DLL - подпрограмме использовать сегмент стека вызвавшей ее программы.

В разделе описаний DLL могут объявляться типы (в том числе и классы), константы и переменные, но они остаются скрытыми от вызывающей программы и могут использоваться только внутри DLL. В разделе описаний помимо стандартных для обычной программы объявлений используется специальный раздел объявления экспортируемых подпрограмм. Этот раздел начинается зарезервированным словом Exports, за которым через запятую перечисляются имена и индексы экспортируемых подпрограмм, описанных до того и помеченных директивой Export:

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17