Главная Случайная страница Контакты | Мы поможем в написании вашей работы! | ||
|
Интерфейс объекта определяют методы и свойства, которые могут быть реализованы классом-наследником этого интерфейса. Они описываются аналогично абстрактным классам, так же, как абстрактные классы, но в отличие от них, не могут иметь экземпляров, не могут иметь реализации никаких своих методов (в Object PASCAL допускается реализация части методов в абстрактные классы). Реализация методов интерфейсов осуществляется в классе, поддерживающем (наследующем) данный интерфейс. Переменная типа интерфейс - это ссылка. Она дает возможность ссылаться на объект, чей класс реализует данный интерфейс. Однако с помощью такой переменной разрешается вызывать только методы, декларированные в данном интерфейсе, а не любые методы данного объекта. Интерфейсы являются альтернативой множественному наследованию, имеют практически все его достоинства и лишены его недостатков. Их использование существенно для написания ПО для распределенных систем на основе COM (the Component Object Model) и CORBA (Common Object Request Broker Architecture). Объекты, поддерживающие интерфейсы, могут взаимодействовать с COM- объектами, написанными на C++ или Java.
Интерфейсы, как и классы, могут быть описаны только в самой наружной области видимости программы или модуля, но не в процедуре или функции. Описание типа для интерфейса имеет вид:
type
interfaceName =
interface (ancestorInterface)
['{GUID}']
список полей
end;
Отличия от классов:
· Не бывает экземпляров, реализующих тип интерфейс.
· Список полей интерфейса может включать только свойства и методы. Поля данных использовать нельзя. Соответственно, спецификаторы read и write должны быть методами.
· Все поля интерфейса всегда имеют тип видимости public (без явного указания); не разрешено использовать спецификаторов видимости (но у массивов может быть использован спецификатор default).
· Не бывает конструкторов и деструкторов.
· Методы не могут быть специфицированы как виртуальные, динамические, перекрытые, абстрактные. Поскольку они не имеют реализации в экземплярах типа, эти различия не имеют значения.
· Наследование через интерфейсы множественное.
· Реализация интерфейса может быть только в классе, при этом он должен реализовать все методы интерфейса (а значит, и все свойства)
Интерфейс, как и класс, наследует все методы прародителя, однако только на уровне абстракций, без реализации методов. Однако интерфейс наследует право реализации этих методов в классе, поддерживающем этот интерфейс. В декларации интерфейса можно указать, что интерфейс наследуется от прародительского интерфейса. Если такого указания нет, то интерфейс является непосредственным потомком IUnknown, который определен в модуле System и является прародителем для всех интерфейсов. В IUnknown продекларировано 3 метода — QueryInterface, _AddRef, Release. QueryInterface предназначен для поддержки интерфейсов объектов. _AddRef, _Release обеспечивают управление ссылками на интерфейсы. Простейший путь реализовать эти методы — создать класс-наследник от tInterfacedObject, описанного в модуле System.
Пример описания интерфейса:
type
IMalloc =
interface(IUnknown)
['{00000002-0000-0000-C000-000000000046}']
function Alloc(Size: Integer): Pointer; stdcall;
functionRealloc(P:Pointer;Size:Integer):Pointer;stdcall;
procedure Free(P: Pointer); stdcall;
function GetSize(P: Pointer): Integer; stdcall;
function DidAlloc(P: Pointer): Integer; stdcall;
procedure HeapMinimize; stdcall;
end;
Перед использованием продекларированного интерфейса он должен быть реализован в классе. Реализация осуществляется с помощью декларации в списке прародителей класса:
type
className =
class (ancestorClass,interface1,...,interfaceN)
memberList
end;
Например,
type
TMemoryManager =
class(TInterfacedObject, IMalloc, IErrorInfo)
...
end;
Когда класс реализует интерфейс, он должен реализовать (или наследовать реализацию) каждого метода, декларированного в интерфейсе. Ниже приведено описание tInterfacedObject из модуля System:
type
TInterfacedObject =
class(TObject, IUnknown)
protected
FRefCount: Integer;
function QueryInterface(const IID: TGUID; out Obj): Integer; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
property RefCount: Integer read FRefCount;
end;
tInterfacedObject реализует интерфейс. Поэтому в нем описаны и реализованы все три метода IUnknown. Классы, реализующие интерфейсы, могут быть использованы как прародители. Класс tInterfacedObject реализует три метода интерфейса IUnknown и поэтому удобен как прародитель для всех классов, реализующих интерфейсы. Когда интерфейс реализован в классе, каждый из его методов реализован соответствующим методом (по умолчанию с тем же именем) и с такой же сигнатурой.
В классе-наследнике можно перекрыть методы реализуемого интерфейса. При этом соответствующий метод должен быть виртуальным или динамическим). Также возможно заново унаследовать интерфейс:
type
IWindow =
interface
['{00000115-0000-0000-C000-000000000146}']
procedure Draw;
...
end;
TWindow =
class(TInterfacedObject, IWindow) //TWindow реализует IWindow
procedure Draw;
...
end;
TFrameWindow =
class(TWindow, IWindow) //TFrameWindow переопределяет реализацию Iwindow
procedure Draw;
...
end;
При этом в классе все методы от прародительской реализации этого интерфейса запираются (не наследуются), в том числе выражения различения методов.
Дата публикования: 2014-11-29; Прочитано: 324 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!