Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
[ Монахов ] Объектно-ориентированное программирование.doc
Скачиваний:
94
Добавлен:
16.08.2013
Размер:
490.5 Кб
Скачать

6.2. Реализация интерфейсов свойством

Директива implements в описании свойства класса позволяет делегировать реализацию интерфейса свойству в реализуемом классе. Например, свойство

property MyInterface: IMyInterface

read FMyInterface

implements IMyInterface;

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

  • может иметь тип класса или интерфейса.

  • не может быть массивом или иметь спецификатор индекса.

  • должно иметь спецификатор read; если имеется метод “read”, он не может быть динамическим (хотя может быть виртуальным) или описывать директиву message.

  • Если свойство типа интерфейс, соответствующий интерфейс или его интерфейс-прародитель должен присутствовать в списке интерфейсов класса, где продекларировано свойство.

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

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 ...

Соседние файлы в предмете Информатика