Object Interfaces in Delphi: Object Interfaces

         

Table of contents

1. Interface Types

Two, interface and inheritance (IInterface and Inheritance)

3. Interface Identification and GUID (Interface Identification and GUIDs)

4. Calling Conventions for Interfaces

5. Interface Properties

6. Forward Declarations


        An object interface, or interface for short, defines the methods that a class can implement. Interfaces are declared as classes, but cannot be instantiated directly and have no method definitions of their own. Instead, it is the responsibility of any class that supports an interface to provide implementations of the interface's methods. A variable of an interface type can refer to an object of a class that implements the interface; however, only methods declared in the interface can be called.

        Interfaces have some of the advantages of multiple inheritance, but without the semantic difficulties. Interfaces are also essential for using distributed object models such as SOAP. Using the distributed object model, custom objects that support interfaces can interact with objects written in C++, Java, and other languages.

1. Interface Types

Interfaces, like classes, can only be declared within the outermost scope of a program or unit, not within stored procedure or function declarations. An interface type declaration has the following form:

type interfaceName = interface (ancestorInterface) ['{GUID}'] memberList end;

Warning: In order to support Win32 COM interoperability, the ancestorInterface and GUID specifications are required. Be sure to specify ancestorInterface and GUID if you want to access the interface via COM .

In most respects, an interface declaration is similar to a class declaration, with the following restrictions: 

  1. Member lists can only include methods and properties. Fields are not allowed in interfaces.
  2. Since interfaces have no fields, read-write specifications for properties must be methods.
  3. All members of an interface are public. Visibility specifiers and storage specifiers are not allowed. (but array properties can be declared as default).
  4. Interfaces have no constructors or destructors. They cannot be instantiated except through classes implementing their methods.
  5. Methods cannot be declared virtual, dynamic, abstract, or override ( virtual , dynamic , abstract , or override ). Since interfaces don't implement their own methods, these names don't mean anything.

Here is an example of an interface declaration: 

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.

Two, interface and inheritance (IInterface and Inheritance)

        Interfaces, like classes, inherit all the methods of their ancestors. But interfaces, unlike classes, do not implement methods. What an interface inherits is the obligation to implement a method, which is passed on to any class that supports the interface.

        The declaration of an interface can specify an ancestor interface. If no ancestor interface is specified, it is a direct descendant of IInterface, which is defined in the System unit and is the ultimate ancestor of all other interfaces. In Win32, IInterface declares three methods: QueryInterface, _AddRef, and _Release.

Note: IInterface is equivalent to IUnknown. In general, platform-independent applications should use IInterface, while specific programs with Win32 dependencies should remain in IUnknown.

        QueryInterface provides methods to obtain references to the different interfaces supported by an object. _AddRef and _Release provide lifetime memory management for interface references. The easiest way to implement these methods is to derive the implementation class from the System unit's TInterfacedObject. You can also implement any of these methods as empty functions, but the COM object must be managed through _AddRef and _Release.

Warning : QueryInterface, _AddRef, and _Release are required to support Win32 COM interoperability. Be sure to implement these methods if you want to access the interface through COM.

3. Interface Identification and GUID (Interface Identification and GUIDs)

An interface declaration can specify a globally unique identifier (GUID), represented by a literal string enclosed in parentheses before the member list. The GUID portion of the declaration must have the following form:

 ['{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}']

        where each x is a hexadecimal digit (0 to 9 or A to 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 the interface has a GUID, an interface lookup can be used to obtain a reference to its implementation.

NOTE: GUIDs are only used for COM interoperability.

        The TGUID and PGUID types declared in the system unit are used to manipulate GUIDs.

type 
     PGUID = ^TGUID;
     TGUID = packed record
       D1: Cardinal;
       D2: Word;
       D3: Word;
       D4: array[0..7] of Byte;
   end;

There are two calling methods supported:

if Supports(Allocator, IMalloc) then ...

or

if Supports(Allocator, IID_IMalloc) then ...

Note: The SysUtils unit provides an overloaded function named Supports that returns true or false when class types and instances support a particular interface represented by a GUID. The Supports function is used in the same way as the Delphi is and as operators. The difference is that the right operand of the Supports function can be a GUID or an interface type associated with a GUID, whereas the right operand of the is and as operands is a type name. See Class References for more information on is and as.

4. Calling Conventions for Interfaces

        The default calling convention for interface methods is register, but interfaces shared between modules (especially interfaces written in different languages) should declare all methods using stdcall. In Win32, you can use safecall to implement the method of dual interface.

5. Interface Properties

        Properties declared in an interface can only be accessed through expressions of interface type, not through class type variables. Also, interface properties are only visible in programs that have the interface compiled.

        In interfaces, the read and write specifications for properties must be methods, since fields are not available.

6. Forward Declarations

        An interface declaration ending with the reserved word interface and a semicolon is a forward declaration if no ancestor, GUID, or member list is specified. A forward declaration must be resolved by a defining declaration of the same interface in the same type declaration section. In other words, between the forward declaration and the defining declaration, there cannot be any other declarations other than other type declarations.

        Forward declarations allow interdependent 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 illegal to derive IWindow from IControl and IControl from IWindow.

Guess you like

Origin blog.csdn.net/sensor_WU/article/details/132492050