RAD Studio (Common)
|
An object interface, or simply interface, defines methods that can be implemented by a class. Interfaces are declared like classes, but cannot be directly instantiated and do not have their own method definitions. Rather, it is the responsibility of any class that supports an interface to provide implementations for the interface's methods. A variable of an interface type can reference an object whose class implements that interface; however, only methods declared in the interface can be called using such a variable.
Interfaces offer some of the advantages of multiple inheritance without the semantic difficulties. They are also essential for using distributed object models (such as SOAP). Using a distributed object model, custom objects that support interfaces can interact with objects written in C++, Java, and other languages.
Interfaces, like classes, can be declared only in the outermost scope of a program or unit, not in a procedure or function declaration. An interface type declaration has the form
type interfaceName = interface (ancestorInterface) ['{GUID}'] memberList end;
type IMalloc = interface(IInterface) ['{00000002-0000-0000-C000-000000000046}'] function Alloc(Size: Integer): Pointer; stdcall; function Realloc(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;
In some interface declarations, the interface reserved word is replaced by dispinterface. This construction (along with the dispid, readonly, and writeonly directives) is platform-specific and is not used in Linux programming.
An interface, like a class, inherits all of its ancestors' methods. But interfaces, unlike classes, do not implement methods. What an interface inherits is the obligation to implement methods, an obligation that is passed onto any class supporting the interface.
The declaration of an interface can specify an ancestor interface. If no ancestor is specified, the interface is a direct descendant of IInterface, which is defined in the System unit and is the ultimate ancestor of all other interfaces. On Win32, IInterface declares three methods: QueryInterface, _AddRef, and _Release
An interface declaration can specify a globally unique identifier (GUID), represented by a string literal enclosed in brackets immediately preceding the member list. The GUID part of the declaration must have the form
['{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}']
where each x is a hexadecimal digit (0 through 9 or A through F). The Type Library editor automatically generates GUIDs for new interfaces. You can also generate GUIDs by pressing Ctrl+Shift+G in the code editor.
A GUID is a 16-byte binary value that uniquely identifies an interface. If an interface has a GUID, you can use interface querying to get references to its implementations.
type PGUID = ^TGUID; TGUID = packed record D1: Longword; D2: Word; D3: Word; D4: array[0..7] of Byte; end;
Supports can be called in either of two ways
if Supports(Allocator, IMalloc) then ...
or
if Supports(Allocator, IID_IMalloc) then ...
The default calling convention for interface methods is register, but interfaces shared among modules (especially if they are written in different languages) should declare all methods with stdcall. On Win32, you can use safecall to implement methods of dual interfaces.
Properties declared in an interface are accessible only through expressions of the interface type; they cannot be accessed through class-type variables. Moreover, interface properties are visible only within programs where the interface is compiled.
In an interface, property read and write specifiers must be methods, since fields are not available.
An interface declaration that ends with the reserved word interface and a semicolon, without specifying an ancestor, GUID, or member list, is a forward declaration. A forward declaration must be resolved by a defining declaration of the same interface within the same type declaration section. In other words, between a forward declaration and its defining declaration, nothing can occur except other type declarations.
Forward declarations allow mutually dependent interfaces. For example,
type IControl = interface; IWindow = interface ['{00000115-0000-0000-C000-000000000044}'] function GetControl(Index: Integer): IControl; . . . end; IControl = interface ['{00000115-0000-0000-C000-000000000049}'] function GetWindow: IWindow; . . . end;
Mutually derived interfaces are not allowed. For example, it is not legal to derive IWindow from IControl and also derive IControl from IWindow.
Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
|
What do you think about this topic? Send feedback!
|