Protected
function Querylnterface( const IID: TGUID; out Obj): Integer; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; Public property RefCount: Integer read FRefCount; End; Если бы в предыдущем примере класс TPainter был описан так: TPainter = class(IPaint) procedure CirclePaint(Canva: TCanvas; X,Y,R: Integer); procedure RectPaint(Canva: TCanvas; X1,Y1,X2,Y2: Integer); End; компилятор потребовал бы описать недостающие методы Queryinterface, _Add И _Releaseкласса TInterfacedObject. Поле FRef Count этого класса служит счетчиком вызовов интерфейсного объекта и используется по принятой в Windows схеме: при каждом обращении к методу Add интерфейса IUnknow счетчик наращивается на единицу, при каждом обращении к Release - на единицу сбрасывается. Когда значение этого поля становится равно 0, интерфейсный объект уничтожается и освобождается занимаемая им память. Если интерфейс предполагаетсяиспользовать в технологиях COM/DCOM или CORBA, его методы должны описывать с директивой stdcall или (для объектов Автоматизации) safecall К интерфейсному объекту можно применить оператор приведения типов as, чтобы использовать нужный интерфейс: procedure PaintObjects(P: TInterfacedObject) var X: IPaint; Begin Try X:= P as IPaint; X.CirclePaint(PaintBoxl.Canvas,0,0,20) Except ShowMessage('Объект не поддерживает интерфейс IPaint') End End; Встретив такое присваивание, компилятор создаст код, с помощью которого вызывается метод Queryinterface интерфейса IUnknow с требованием вернуть ссылку на интерфейс IPaint. Если объект не поддерживает указанный интерфейс, возникает исключительная ситуация. Интерфейсы, рассчитанные на использование в удаленных объектах, должны снабжаться глобально-уникальным идентификатором (guiD). Например: IPaint = interface ['{A4AFEB60-7705-11D2-8B41-444553540000}'] procedure CirclePaint(Canva: TCanvas; X,Y,R: Integer); procedure RectPaint(Canva: TCanvas; Xl,Yl,X2,Y2: Integer); end; Глобально-уникальные идентификаторы создаются по специальной технологии, гарантирующей ничтожно малую вероятность того, что два guid совпадут. Эта технология включена в Windows 32: чтобы получить guid для вновь созданного интерфейса в среде Delphi, достаточно нажать клавиши Ctrl+Shift+G. Для работы с guid в модуле System объявлены следующие типы: Type PGUID = ^TGUID; TGUID = record Dl: LongWord; D2: Word; D3: Word; D4: array [0..7] of Byte; End; Программист может объявлять типизированные константы типа tguid, например: const IID_IPaint: TGUID= ['{A4AFEB61-7705-11D2-8B41-444553540000}']; Константы guid могут использоваться вместо имен интерфейсов при вызове подпрограмм. Например, два следующих обращения идентичны: procedure Paint(const IID: TGUID); Paint(IPaint); Paint(IID_Paint); С помощью зарезервированного слова implements программист может делегировать какому-либо свойству некоторого класса полномочия интерфейса. Это свойство должно иметь тип интерфейса или класса. Если свойство имеет тип интерфейса, имя этого интерфейса должно указываться в списке родителей класса, как если бы это был интерфейсный класс: Type IMylnterface = interface procedure P1; procedure P2; End; TMyClass = class(TObject, IMylnterface) FMyInterface: IMylnterface; property Mylnterface: IMylnterface read FMyInterface implements IMylnterface; End; Обратите внимание: в этом примере класс TMyciass не является интерфейсным, т. е. классом, в котором исполняются методы p1 и P2. Однако если из него убрать определение уполномоченного свойства Mylnterface, он станет интерфейсным, и в нем должны быть описаны методы интерфейса IMylnterface. Уполномоченное свойство обязательно должно иметь часть read. Если оно имеет тип класса, класс, в котором оно объявлено, не может иметь других уполномоченных свойств. 9.4.2. Объекты Автоматизации и интерфейс IDispatch В технологии OLE активно используются так называемые объекты Автоматизации (Automation objects). Эти объекты представляют собой экземпляры интерфейсных классов, родительским интерфейсом которых является специальный интерфейс IDispatch. Отличительной особенностью IDispatch является то обстоятельство, что методы объекта Автоматизации никогда не вызываются напрямую, но всегда - с помощью метода invoke интерфейса IDispatch. Управление объектами СОМ с помощью выполнения методов IDispatch называется маршализацией (marshaling). Для объявления класса Автоматизации используется специальное зарезервированное слово dispinterface, а перечисляемые в нем методы и свойства должны снабжаться целочисленными идентификаторами, которые вставляются в конце описания методов (свойств) после зарезервированных слов dispid: Type IStringsDisp = dispinterface [ ' {EE05DFE2-5549-11DO-9EA9-0020AF3D82DA} ' ] property ControlDefault[Index: Integer]: OleVariant dispid 0; default-function Count: Integer;
|