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


